且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

《Python面向对象编程指南》——2.4 __bool__()方法

更新时间:2022-09-27 14:05:59

本节书摘来自异步社区《Python面向对象编程指南》一书中的第2章,第2.4节,作者[美]Steven F. Lott, 张心韬 兰亮 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.4 __bool__()方法

Python中有很多关于真假性的定义。参考手册中列举了许多和False等价的值,包括False、0、''、()、[]和{}。其他大部分的对象都和True等价。

通常,我们会用下面的语句来测试一个对象是否“非空”。

if some_object:
   process( some_object )

默认情况下,这个是内置的bool()函数的逻辑。这个函数依赖于一个给定对象的__bool__()方法。

默认的__bool__()方法返回True。我们可以通过下面的代码来验证这一点。

>>> x = object()
>>>bool(x)
True

对大多数类来说,这是完全正确的。大多数对象都不应该和False等价。但是,对于集合,这样的行为并不总是正确的。一个空集合应该和False等价,而一个非空集合应该返回True。或许,应该给我们的Deck集合对象增加一个类似的方法。

如果我们在封装一个列表,我们可能会写下面这样的代码。

def __bool__( self ):
   return bool( self._cards )

这段代码将__bool__()的计算委托给了内部的集合_cards。

如果我们在扩展一个列表,可能会写下面这样的代码:

def __bool__( self ):
   return super().__bool__( self )

这段代码使用了基类中定义的__bool__()函数。

在这两个例子中,我们都将布尔值的计算委托给其他对象。在封装的例子中,我们委托给了一个内部的集合。在扩展的例子中,我们委托给了基类。不管是封装还是扩展,一个空集合的布尔值都是False。这会让我们很清楚Deck对象是否已经被处理完了。

现在,我们就可以像下面这样使用Deck。

d = Deck()
while d:
   card= d.pop()
   # process the card

这段代码会处理完Deck中所有的牌,当所有的牌都处理完时,也不会抛出IndexError异常。