Python __bool__ 方法
最后修改于 2025 年 4 月 8 日
本综合指南探讨了 Python 的 __bool__
方法,该特殊方法定义了对象的真值。我们将介绍基本用法、真值规则、实际示例和常见模式。
基本定义
调用 __bool__
方法来实现真值测试和内置的 bool()
函数。它应该返回 True
或 False
。
当未定义 __bool__
时,Python 会回退到 __len__
。如果两者都未定义,则默认情况下对象被认为是 True
。此方法对于控制流语句至关重要。
基本 __bool__ 实现
这是一个简单的示例,展示了如何实现 __bool__
来控制对象的真值。该方法必须返回一个布尔值。
class Account: def __init__(self, balance): self.balance = balance def __bool__(self): return self.balance > 0 account1 = Account(100) account2 = Account(-50) print(bool(account1)) # True print(bool(account2)) # False if account1: print("Account has funds")
此示例定义了一个 Account
类,如果帐户余额为正,则认为该帐户为真值。 __bool__
方法封装了此业务逻辑。
当对象在布尔上下文中(如 if
语句或使用 bool()
函数)使用时,会自动调用该方法。
__bool__ 与 __len__ 回退
当未定义 __bool__
时,Python 使用 __len__
作为回退。此示例显示了这两种方法如何协同工作。
class ShoppingCart: def __init__(self, items): self.items = items def __len__(self): return len(self.items) def __bool__(self): return any(item.price > 0 for item in self.items) class Item: def __init__(self, price): self.price = price cart1 = ShoppingCart([Item(10), Item(20)]) cart2 = ShoppingCart([Item(0), Item(0)]) print(bool(cart1)) # True (__bool__ returns True) print(bool(cart2)) # False (__bool__ returns False) print(bool(ShoppingCart([]))) # False (__len__ returns 0)
此示例表明 __bool__
优先于 __len__
。 对于空购物车,当未定义 __bool__
时,Python 会回退到 __len__
。
只有当购物车包含至少一个价格为正的商品时,才认为该购物车为真值,这展示了自定义的真值逻辑。
数据验证中的真值
__bool__
可用于实现验证逻辑,使对象可在布尔上下文中使用,以检查其有效性。
class UserProfile: def __init__(self, name, email): self.name = name self.email = email self._validate() def _validate(self): self.is_valid = ( isinstance(self.name, str) and '@' in self.email ) def __bool__(self): return self.is_valid valid_user = UserProfile("Alice", "alice@example.com") invalid_user = UserProfile(123, "bobexample.com") print(bool(valid_user)) # True print(bool(invalid_user)) # False if not invalid_user: print("Profile is invalid")
此示例使用 __bool__
来公开验证状态。 该方法返回初始化期间设置的内部 is_valid
标志。
当您希望对象通过布尔测试以自然的方式自我报告其有效性时,此模式非常有用。
自定义容器真值
对于类似容器的对象,__bool__
可以根据容器状态提供有意义的真值,类似于内置容器。
class Playlist: def __init__(self, songs): self.songs = list(songs) def __bool__(self): return len(self.songs) > 0 and any( song.duration > 0 for song in self.songs ) def __len__(self): return len(self.songs) class Song: def __init__(self, duration): self.duration = duration empty_playlist = Playlist([]) playlist_with_silent_tracks = Playlist([Song(0), Song(0)]) valid_playlist = Playlist([Song(180), Song(240)]) print(bool(empty_playlist)) # False print(bool(playlist_with_silent_tracks)) # False print(bool(valid_playlist)) # True
只有当此 Playlist
类包含持续时间为正的歌曲时,才认为它是真值。它将长度检查与内容验证相结合。
该实现遵循 Python 的原则,即空容器为假值,但使用关于什么构成“有效”播放列表的特定于域的逻辑对其进行扩展。
有状态对象中的 __bool__
对于有状态对象,__bool__
可以反映当前状态,使状态检查更直观和 Pythonic。
class TrafficLight: def __init__(self): self._state = 'red' def change(self): if self._state == 'red': self._state = 'green' elif self._state == 'green': self._state = 'yellow' else: self._state = 'red' def __bool__(self): return self._state == 'green' light = TrafficLight() print(bool(light)) # False light.change() print(bool(light)) # True light.change() print(bool(light)) # False
此交通灯实现使用 __bool__
来指示灯是否为绿色。布尔值随灯的状态而变化。
当检查对象状态时,此模式使代码更具可读性,因为 if light:
清楚地表达了检查绿色状态的意图。
最佳实践
- 只返回布尔值:
__bool__
必须返回True
或False
- 保持简单: 真值应该是显而易见且可预测的
- 考虑
__len__
: 对于集合,适当地定义这两种方法 - 记录行为: 清楚地记录您的真值规则
- 遵循 Python 约定: 空集合应该为假值
资料来源
作者
列出所有 Python 教程。