Как хранить одно и то же значение в двух переменных, независимо изменяя их в Python? - PullRequest
0 голосов
/ 20 мая 2018

Я пытаюсь создать рекурсивную функцию, которая возвращает набор всех непустых подмножеств [1,2,3,...,n] чисел.

Вот мой код:

def subsets(n):
    if n == 2:
        return ([1], [2], [1, 2])
    else:
        previous = subsets(n - 1)
        temp = previous
        result = ()
        for set in previous:
            set += [n]
            result += (set,)
        return temp + ([n],) + result

this not 'temp сохраняет значение previous после его изменения.Просто изменить его на -

previous = subsets(n - 1)
temp = subsets(n - 1)

работает, но, очевидно, не очень эффективное решение.Я также попытался -

previous,temp = subsets(n - 1)

, но это вызывает ошибку "слишком много значений для распаковки".Что мне делать?

Ответы [ 4 ]

0 голосов
/ 20 мая 2018

Минимальное изменение вашего кода, вероятно, будет заключаться не в изменении set с помощью set += ([n], ), а в создании нового кортежа с set + ([n], ).temp тогда не используется и может быть удален.Полный код:

def subsets(n):
    if n == 2:
        return ([1], [2], [1, 2])
    else:
        previous = subsets(n - 1)
        result = ()
        for set in previous:
            result += (set + [n],)
        return previous + ([n],) + result

Поскольку result += ... каждый раз создает новый кортеж, это неэффективно и должно быть заменено выражением генератора:

def subsets(n):
    if n == 2:
        return ([1], [2], [1, 2])
    else:
        previous = subsets(n - 1)
        return previous + ([n],) + tuple(set + [n] for set in previous)
0 голосов
/ 20 мая 2018

Вам нужна копия глубиной previous, а не просто еще одна ссылка (temp = previous) или теневая копия (temp = previous[:]).

previous = ([1],)
temp = previous[:]
myset = previous[0]
myset += [2]
print(previous)  # ([1, 2],) 
print(previous)  # ([1, 2],)

Что вы можетеделать:

for set in previous:
    set = list(set)  # make a copy
    set += [n]
    result += (set,)
0 голосов
/ 20 мая 2018

Хочу отметить, что возвращение всех подмножеств - это то, что вы можете эффективно выполнить с помощью itertools.

import itertools

def subsets(n):
    for x in range(1, n + 1):
        yield from itertools.combinations(range(1, n + 1), x)

print(*subsets(3))  # (1,) (2,) (3,) (1, 2) (1, 3) (2, 3) (1, 2, 3)

. Это возвращает генератор, который сэкономит много памяти, поскольку набор мощности растет в геометрической прогрессии.

0 голосов
/ 20 мая 2018

Поскольку вы возвращаете кортеж, Python возвращает его ссылку.Вот почему при изменении previous, temp также изменяется.

Чтобы сохранить их независимо, вы можете использовать оператор среза:

previous = subsets(n - 1)
temp = previous[:]

Использование [:] скопирует previous содержимого для temp вместо присвоения previous ссылки на temp.


РЕДАКТИРОВАНИЕ:

Если у вас есть некоторая вложенность внутри вашей структуры данных, вам придетсяиспользуйте глубокую копию:

import copy # at the top of your script

previous = subsets(n - 1)
temp = copy.deepcopy(previous)

Спасибо @Paul Panzer за указание на это в комментариях.

...