考虑以下代码:
>>> class X:
... pass
...
>>> x = X()
>>> len(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'X' has no len()
>>> bool(x)
True
但是,当试图模仿本文__len__
时,它是行不通的。
>>> class Y:
... def __len__(self):
... raise TypeError
...
>>> y = Y()
>>> len(y)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __len__
TypeError
>>> bool(y)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __len__
TypeError
有没有办法编写一个__len__
函数,就像未实现一样?
答案 0 :(得分:3)
bool()
测试对象的真值,因此您要查看rules for Truth Value Testing:
默认情况下,除非对象的类定义了
__bool__()
方法(该方法返回{{1})或False
(当与该对象一起调用时返回零),否则认为该对象为真。
您仅实现了一个故意中断的__len__()
方法,在调用时会引发__len__
。但是TypeError
将在有实现的情况下调用它,并且没有其他可用的选项来确定真值。
确定真值时,__bool__
is preferred over __len__
:
未定义此方法时,将调用
bool()
(如果已定义),并且如果其结果为非零,则认为该对象为true。
演示:
__len__()
请注意,当>>> class Z:
... def __bool__(self):
... return True
... def __len__(self):
... raise TypeError
...
>>> len(Z())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __len__
TypeError
>>> bool(Z())
True
钩子没有实现时,是len()
函数实现引发TypeError
。 __len__
实现不会引发任何异常,这会让您假装它实际上并未实现,如果调用它,则会传播它引发的任何异常,因为您通常会想知道该实现是否为以某种方式破裂。