Когда я пишу этот код:
polly = "alive"
palin = ["parrot", polly]
print(palin)
polly = "dead"
print(palin)
Я думал, что это выведет это:
"['parrot', 'alive']"
"['parrot', 'dead']"
Однако это не так. Как получить его для вывода этого?
Когда я пишу этот код:
polly = "alive"
palin = ["parrot", polly]
print(palin)
polly = "dead"
print(palin)
Я думал, что это выведет это:
"['parrot', 'alive']"
"['parrot', 'dead']"
Однако это не так. Как получить его для вывода этого?
Переменные 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.
Перед вторым выражением печати сохраните новые значения в palin
:
palin = ["parrot", polly]
Когда вы помещаете строку в список, список содержит копию строки. Неважно, была ли строка первоначально переменной, литеральное значение, результат вызова функции или что-то еще; к тому времени, когда список увидит его, это просто строковое значение. Изменение того, что сгенерировало строку позже, никогда не повлияет на список.
Если вы хотите сохранить ссылку на значение, которое будет замечено при изменении этого значения, обычным механизмом является использование списка, содержащего "ссылочное" значение. Применив это к вашему примеру, вы завершаете вложенный список:
polly = ["alive"]
palin = ["parrot", polly]
print(palin)
polly[0] = "dead"
print(palin)
Список будет содержать только значения, а не ссылки на переменные, как вам хотелось бы. Тем не менее, вы можете сохранить лямбда в списке, а лямбда - посмотреть значение переменной.
>>> a = 'a'
>>> list = ['a',lambda: a]
>>> list[1]
<function <lambda> at 0x7feff71dc500>
>>> list[1]()
'a'
>>> a = 'b'
>>> list[1]()
'b'
Вы не можете. Присвоение голого имени Python всегда только переименовывает имя, и вы не можете настроить или контролировать эту операцию.
Что вы можете сделать, это сделать polly
изменчивый объект вместо строки и изменить его значение вместо того, чтобы пересобирать имя. Простой пример:
>>> polly = ['alive']
>>> items = ['parrot', polly]
>>> items
['parrot', ['alive']]
>>> polly[0] = 'dead'
>>> items
['parrot', ['dead']]
Другие ответы объяснили, что происходит хорошо.
Это одна из (нескольких) проблем, которые мотивируют использование объектов. Например, можно сделать следующее:
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