为什么 `__iter__` 在定义为实例变量时不起作用?
Why `__iter__` does not work when defined as an instance variable?
如果我按如下方式定义 __iter__
方法,它将不起作用:
class A:
def __init__(self):
self.__iter__ = lambda: iter('text')
for i in A().__iter__():
print(i)
iter(A())
结果:
t
e
x
t
Traceback (most recent call last):
File "...\mytest.py", line 10, in <module>
iter(A())
TypeError: 'A' object is not iterable
如您所见,调用 A().__iter__()
有效,但 A()
不可迭代。
但是,如果我为 class 定义 __iter__
,那么它将起作用:
class A:
def __init__(self):
self.__class__.__iter__ = staticmethod(lambda: iter('text'))
# or:
# self.__class__.__iter__ = lambda s: iter('text')
for i in A():
print(i)
iter(A())
# will print:
# t
# e
# x
# t
有谁知道为什么python会这样设计?即为什么 __iter__
作为实例变量不起作用?你不觉得不直观吗?
这是设计使然。您可以在此处找到详细说明:https://docs.python.org/3/reference/datamodel.html#special-method-lookup
简短回答:必须在 class 对象本身上设置特殊方法,以便解释器始终调用。
长答案:这背后的想法是加快众所周知的建设。在您的示例中:
class A:
def __init__(self):
self.__iter__ = lambda: iter('text')
您在现实生活中多久会编写这样的代码?所以,Python 做了什么 - 它跳过了实例的字典查找,即 iter(A())
根本不 "see" 那个 self.__iter__
,实际上是 self.__dict__['__iter__']
案件。
它还会跳过所有 __getattribute__
实例和元class 查找,从而获得显着的加速。
如果我按如下方式定义 __iter__
方法,它将不起作用:
class A:
def __init__(self):
self.__iter__ = lambda: iter('text')
for i in A().__iter__():
print(i)
iter(A())
结果:
t
e
x
t
Traceback (most recent call last):
File "...\mytest.py", line 10, in <module>
iter(A())
TypeError: 'A' object is not iterable
如您所见,调用 A().__iter__()
有效,但 A()
不可迭代。
但是,如果我为 class 定义 __iter__
,那么它将起作用:
class A:
def __init__(self):
self.__class__.__iter__ = staticmethod(lambda: iter('text'))
# or:
# self.__class__.__iter__ = lambda s: iter('text')
for i in A():
print(i)
iter(A())
# will print:
# t
# e
# x
# t
有谁知道为什么python会这样设计?即为什么 __iter__
作为实例变量不起作用?你不觉得不直观吗?
这是设计使然。您可以在此处找到详细说明:https://docs.python.org/3/reference/datamodel.html#special-method-lookup
简短回答:必须在 class 对象本身上设置特殊方法,以便解释器始终调用。
长答案:这背后的想法是加快众所周知的建设。在您的示例中:
class A:
def __init__(self):
self.__iter__ = lambda: iter('text')
您在现实生活中多久会编写这样的代码?所以,Python 做了什么 - 它跳过了实例的字典查找,即 iter(A())
根本不 "see" 那个 self.__iter__
,实际上是 self.__dict__['__iter__']
案件。
它还会跳过所有 __getattribute__
实例和元class 查找,从而获得显着的加速。