为什么在此代码中更改了变量 a?
Why is the variable a is changed in this code?
class PowTwo:
"""Class to implement an iterator
of powers of two"""
def __init__(self, max=0):
self.max = max
def __iter__(self):
self.n = 0
return self
def __next__(self):
if self.n <= self.max:
result = 2 ** self.n
self.n += 1
return result
else:
raise StopIteration
a = PowTwo(3)
b = iter(a)
print(next(a))
没有这个片段 b = iter(a)
,输出是
Traceback (most recent call last):
File "/Users/Mark/test2.py", line 20, in <module>
print(next(a))
File "/Users/Mark/test2.py", line 13, in __next__
if self.n <= self.max:
AttributeError: 'PowTwo' object has no attribute 'n'
我的问题:
b = iter(a)
我没用a = iter(a)
。这里变量a怎么变了?
您的 __iter__
是可变的:它将对象的 n
属性设置为 0
。这是代码中 n
的 only 初始化。如果不调用__iter__
,__next__
查找时不会找到n
。
可变 __iter__
方法不是个好主意。您应该在 __init__
.
中执行初始化
Python 对象可以分配给多个名称。所有这些名称都将指代同一个实际对象。例如:
a = [1, 2, 3]
b = a
a
和 b
指的是同一个对象。设置b[0] = 0
也会影响a
,因为是同一个对象。这给初学者带来了很大的痛苦。
要将对象绑定到名称,您可以分配它。作业有多种形式。例如,def
和 class
分别将函数和 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
Return 值的工作方式类似,但相反。函数中的对象被分配给外部作用域中的名称。
现在假设您有一个对象 a = PowTwo(3)
。当您对其调用 b = iter(a)
时,会发生以下情况:
- 对
iter
的调用等同于PowTwo.__iter__(a)
- 您在全局范围内分配给
a
的对象绑定到 __iter__
中的参数 self
__iter__
中的对象 self
通过 return 调用 绑定到 b
现在 a
和 b
指的是同一个对象。之后调用 next(a)
或 next(b)
会将同一个对象传递给 next
,因为两个名称都绑定到它。
如果您分配了 a = iter(a)
,您将重新绑定 a
到它自己。虽然技术上不是空操作,但它相当于只调用 iter(a)
并丢弃冗余的 return 值。
class PowTwo:
"""Class to implement an iterator
of powers of two"""
def __init__(self, max=0):
self.max = max
def __iter__(self):
self.n = 0
return self
def __next__(self):
if self.n <= self.max:
result = 2 ** self.n
self.n += 1
return result
else:
raise StopIteration
a = PowTwo(3)
b = iter(a)
print(next(a))
没有这个片段 b = iter(a)
,输出是
Traceback (most recent call last):
File "/Users/Mark/test2.py", line 20, in <module>
print(next(a))
File "/Users/Mark/test2.py", line 13, in __next__
if self.n <= self.max:
AttributeError: 'PowTwo' object has no attribute 'n'
我的问题:
b = iter(a)
我没用a = iter(a)
。这里变量a怎么变了?
您的 __iter__
是可变的:它将对象的 n
属性设置为 0
。这是代码中 n
的 only 初始化。如果不调用__iter__
,__next__
查找时不会找到n
。
可变 __iter__
方法不是个好主意。您应该在 __init__
.
Python 对象可以分配给多个名称。所有这些名称都将指代同一个实际对象。例如:
a = [1, 2, 3]
b = a
a
和 b
指的是同一个对象。设置b[0] = 0
也会影响a
,因为是同一个对象。这给初学者带来了很大的痛苦。
要将对象绑定到名称,您可以分配它。作业有多种形式。例如,def
和 class
分别将函数和 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
Return 值的工作方式类似,但相反。函数中的对象被分配给外部作用域中的名称。
现在假设您有一个对象 a = PowTwo(3)
。当您对其调用 b = iter(a)
时,会发生以下情况:
- 对
iter
的调用等同于PowTwo.__iter__(a)
- 您在全局范围内分配给
a
的对象绑定到__iter__
中的参数 __iter__
中的对象self
通过 return 调用 绑定到
self
b
现在 a
和 b
指的是同一个对象。之后调用 next(a)
或 next(b)
会将同一个对象传递给 next
,因为两个名称都绑定到它。
如果您分配了 a = iter(a)
,您将重新绑定 a
到它自己。虽然技术上不是空操作,但它相当于只调用 iter(a)
并丢弃冗余的 return 值。