Подтвердить что ты не робот

Список Python не отражает переменные изменения

Когда я пишу этот код:

polly = "alive"
palin = ["parrot", polly]
print(palin)
polly = "dead"
print(palin)

Я думал, что это выведет это:

"['parrot', 'alive']"
"['parrot', 'dead']"

Однако это не так. Как получить его для вывода этого?

4b9b3361

Ответ 1

Переменные Python содержат ссылки на значения. Таким образом, когда вы определяете список palin, вы передаете значение, на которое ссылается polly, а не сама переменная.

Вы должны представлять ценности как воздушные шары, а переменные - это потоки, привязанные к этим воздушным шарам. "alive" - это воздушный шар, polly - это просто поток этого шара, а в списке palin есть другой поток, привязанный к тому же воздушному шару. В python список - это просто серия потоков, все номера которых начинаются с 0.

То, что вы делаете дальше, привязывает строку polly к новому шару "dead", но список все еще держится за старый поток, привязанный к воздушному шару "alive".

Вы можете заменить этот поток на "alive", удерживаемый списком, переназначив список по индексу, чтобы ссылаться на каждый поток; в вашем примере, что поток 1:

>>> palin[1] = polly
>>> palin
['parrot', 'dead']

Здесь я просто привязал поток palin[1] к тому же, с чем привязан polly, что бы это ни было.

Обратите внимание, что любая коллекция в python, такая как dict, set, tuple и т.д., также являются наборами потоков. Некоторые из них могут обмениваться потоками для разных потоков, таких как списки и dicts, и что делает что-то в python "изменчивым".

Строки, с другой стороны, не изменяемы. Как только вы определяете строку типа "dead" или "alive", это один воздушный шар. Вы можете связать его потоком (переменная, список или что-то еще), но вы не можете заменить буквы внутри него. Вы можете связать этот поток только с совершенно новой строкой.

Большинство вещей в python могут действовать как воздушные шары. Целые числа, строки, списки, функции, экземпляры, классы, все могут быть привязаны к переменной или привязаны к контейнеру.

Возможно, вам захочется прочитать трактат Ned Batchelder по именам Python.

Ответ 2

Перед вторым выражением печати сохраните новые значения в palin:

palin = ["parrot", polly]

Ответ 3

Когда вы помещаете строку в список, список содержит копию строки. Неважно, была ли строка первоначально переменной, литеральное значение, результат вызова функции или что-то еще; к тому времени, когда список увидит его, это просто строковое значение. Изменение того, что сгенерировало строку позже, никогда не повлияет на список.

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

polly = ["alive"]
palin = ["parrot", polly]
print(palin)
polly[0] = "dead"
print(palin)

Ответ 4

Список будет содержать только значения, а не ссылки на переменные, как вам хотелось бы. Тем не менее, вы можете сохранить лямбда в списке, а лямбда - посмотреть значение переменной.

>>> a = 'a'
>>> list = ['a',lambda: a]
>>> list[1]
<function <lambda> at 0x7feff71dc500>
>>> list[1]()
'a'
>>> a = 'b'
>>> list[1]()
'b'

Ответ 5

Вы не можете. Присвоение голого имени Python всегда только переименовывает имя, и вы не можете настроить или контролировать эту операцию.

Что вы можете сделать, это сделать polly изменчивый объект вместо строки и изменить его значение вместо того, чтобы пересобирать имя. Простой пример:

>>> polly = ['alive']
>>> items = ['parrot', polly]
>>> items
['parrot', ['alive']]
>>> polly[0] = 'dead'
>>> items
['parrot', ['dead']]

Ответ 6

Другие ответы объяснили, что происходит хорошо.

Это одна из (нескольких) проблем, которые мотивируют использование объектов. Например, можно сделать следующее:

class Animal:
    def __init__(self, aniType, name):
        self.aniType = aniType
        self.name = name
        self.isAlive = True

    def kill(self):
        self.isAlive = False

    def getName(self):
        return self.name

    def getType(self):
        return self.aniType

    def isLiving(self):
        return self.isAlive


polly = Animal("parrot", "polly")

print(polly.getName()+' the '+polly.getType()+' is alive?')
print(polly.isLiving())

polly.kill()

print(polly.getName()+' the '+polly.getType()+' is alive?')
print(polly.isLiving())

Вначале это может выглядеть как много кода для простой задачи, но объекты часто являются способами для таких вещей, потому что они помогают держать все организованным.

Здесь вывод этой программы:

polly the parrot is alive?
True
polly the parrot is alive?
False