Python объектам можно присвоить несколько имен. Все эти имена будут относиться к одному и тому же фактическому объекту. Например:
a = [1, 2, 3]
b = a
Оба a
и b
относятся к одному и тому же объекту. Настройка b[0] = 0
также повлияет на a
, потому что это тот же объект. Это причиняет много горя новичкам.
Чтобы привязать объект к имени, вы назначаете его. Задания имеют множество форм. Например, def
и class
присваивают имена объектам функций и классов соответственно. Эти имена не являются специальными, и вы можете повторно связать их по своему желанию:
def a():
print('Hi')
b = a # b now refers to a function object
a = 1 # a is now an integer, while b is the original function
Другой тип присваивания происходит, когда вы передаете аргументы функции. Передаваемые вами объекты привязаны к локальным именам в списке аргументов. Локальные имена функций относятся к тем же самым объектам, которые вы передали, а не к копиям:
a = 1
def f(x):
print(x is a)
f(a) # True
Возвращаемые значения работают аналогично, но в обратном порядке. Объекту в функции присваивается имя во внешней области видимости.
Теперь предположим, что у вас есть объект a = PowTwo(3)
. Когда вы вызываете на нем b = iter(a)
, происходит следующее:
- Вызов
iter
эквивалентен PowTwo.__iter__(a)
- Объект, который вы назначили
a
в глобальная область видимости привязана к аргументу self
в __iter__
- Объект
self
в __iter__
привязан к b
вызовом возврата
Теперь a
и b
относятся к одному и тому же объекту. Вызов next(a)
или next(b)
после этого передаст тот же объект в next
, поскольку к нему привязаны оба имени.
Если бы вы присвоили a = iter(a)
, вы бы повторно связали a
себе. Хотя технически это не означает бездействие, это было бы эквивалентно простому вызову iter(a)
и отказу от избыточного возвращаемого значения.