Rus*_*sky 4 python casting duck-typing list object
构造函数构建一个列表,其项目与iterable的项目相同且顺序相同.iterable可以是序列,支持迭代的容器,也可以是迭代器对象.如果iterable已经是一个列表,则会生成并返回一个副本,类似于iterable [:] ...
但是如果我有一个a我的类的对象A,那就实现了__iter__,__len__并且__getitem__,使用哪个接口list(a)来迭代我的对象以及它背后的逻辑是什么?
class A(object):
def __iter__(self):
print '__iter__ was called'
return iter([1,2,3])
def __len__(self):
print '__len__ was called'
return 3
def __getitem__(self, index):
print '__getitem(%i)__ was called' % index
return index+1
a = A()
list(a)
Run Code Online (Sandbox Code Playgroud)
输出
__iter__ was called
__len__ was called
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
A.__iter__被称为第一,好的.但为什么那么A.__len__被称为?然后为什么A.__getitem__没有被召唤?
__iter__发电机而这改变了魔法方法调用的顺序!
class B(object):
def __iter__(self):
print '__iter__ was called'
yield 1
yield 2
yield 3
def __len__(self):
print '__len__ was called'
return 3
def __getitem__(self, index):
print '__getitem(%i)__ was called' % index
return index+1
b = B()
list(b)
Run Code Online (Sandbox Code Playgroud)
输出
__len__ was called
__iter__ was called
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
为什么B.__len__现在先叫?但为什么然后B.__getitem__没有被调用,转换完成了B.__iter__?
什么最让我困惑的是呼叫的原因的顺序__len__,并__iter__在案件不同的是A和B?
呼叫顺序没有改变.__iter__仍然首先被调用,但是__iter__当__iter__生成器时调用不会立即运行函数体.该print只发生一次next被调用.
__len__被调用是一个实现细节.Python需要提示为列表分配多少空间,因此它会调用_PyObject_LengthHint您的对象,len如果对象支持它,则使用该对象.预期呼叫len对象通常会很快并且没有可见的副作用.