查看: 242|回复: 0

Python布尔类型bool真值测试与短路求值实践

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在Python脚本中,条件分支、循环控制和业务规则几乎都依赖布尔判断。bool只有True和False两个值,但真值测试、比较运算、逻辑运算和短路求值有不少细节。原文围绕这些点给出了示例,下面按代码实现、参数含义、错误原因和业务场景重组说明。

一、True/False字面量与bool/int关系
Python布尔字面量首字母必须大写,true和false只是普通变量名,没有布尔含义。bool是int的子类,因此True==1、False==0成立,True+True为2;但True is 1为False,二者不是同一对象。原文示例:
  1. is_active = True
  2. is_deleted = False
  3. print(type(True))  # <class 'bool'>
  4. print(isinstance(True, int))  # True
  5. print(True == 1)  # True
  6. print(False == 0)  # True
  7. print(True + True)  # 2
  8. print(True * 10)  # 10
  9. print(bool.__bases__)  # (<class 'int'>,)
  10. print(issubclass(bool, int))  # True
  11. scores = [True, False, True, True]
  12. print(sum(scores))  # 3
  13. print(True == 1)  # True
  14. print(True is 1)  # False
复制代码
日常使用把True/False当纯布尔值即可,不要依赖bool是int子类来做业务判断。

二、真值测试与自定义对象
任何对象放进if或while条件时,Python都会按真值规则判断。原文列出的假值包括None、False、0、0.0、0j、空字符串、空列表、空字典、空元组、空集合和空的range;其他值通常为True。常见误区是字符串内容看起来像假值:bool('False')为True,bool('0')为True,bool(' ')也为True,因为非空字符串都是真值;bool(-1)同样为True。
  1. print(bool(None))  # False
  2. print(bool(0))  # False
  3. print(bool(''))  # False
  4. print(bool([]))  # False
  5. print(bool({}))  # False
  6. print(bool(()))  # False
  7. print(bool(set()))  # False
  8. print(bool(range(0)))  # False
  9. print(bool('False'))  # True
  10. print(bool('0'))  # True
  11. print(bool(' '))  # True
  12. print(bool([0]))  # True
  13. print(bool([None]))  # True
  14. print(bool({False: True}))  # True
  15. print(bool(-1))  # True
复制代码
自定义对象可通过__bool__控制真值;没有__bool__时,Python会尝试__len__,返回0为False,否则为True。例如用户对象按is_active判断,购物车按items长度判断:
  1. class User:
  2.     def __init__(self, name, is_active=True):
  3.         self.name = name
  4.         self.is_active = is_active
  5.     def __bool__(self):
  6.         '''自定义真值判断:只有活跃用户才是True'''
  7.         return self.is_active
  8. active_user = User('小明', True)
  9. inactive_user = User('小红', False)
  10. print(bool(active_user))  # True
  11. print(bool(inactive_user))  # False
  12. class ShoppingCart:
  13.     def __init__(self):
  14.         self.items = []
  15.     def add(self, item):
  16.         self.items.append(item)
  17.     def __len__(self):
  18.         '''定义len()的行为'''
  19.         return len(self.items)
  20. cart = ShoppingCart()
  21. print(bool(cart))  # False
  22. cart.add('Python编程书')
  23. print(bool(cart))  # True
复制代码

三、比较运算与链式比较
Python支持==、!=、<、>、<=、>=六种比较运算,也支持数学式链式比较。链式比较会按and逻辑执行,但中间对象只计算一次。不同数字类型可比较,例如5==5.0、5==5+0j;字符串按Unicode码点比较;Python 3中很多不同类型不能直接用<比较,会抛出TypeError。
  1. x, y = 10, 20
  2. print(x == y)  # False
  3. print(x != y)  # True
  4. print(x < y)  # True
  5. print(x > y)  # False
  6. print(x <= y)  # True
  7. print(x >= y)  # False
  8. age = 25
  9. print(18 <= age <= 30)  # True
  10. print(18 <= age and age <= 30)  # True
  11. a, b, c, d = 1, 2, 2, 3
  12. print(a < b == c < d)  # True
  13. print(5 == 5.0)  # True
  14. print(5 == 5 + 0j)  # True
  15. print(5 == True)  # True,但不要依赖
  16. print('apple' < 'banana')  # True
  17. print('a' < 'A')  # False
  18. # print('hello' < 5)  # TypeError
  19. # print([1, 2] < (1, 2))  # TypeError
复制代码

四、逻辑运算、短路求值与返回值
and、or、not是Python的逻辑运算符。and左侧为假时不再计算右侧,or左侧为真时不再计算右侧,这就是短路求值。它可用于避免不必要的函数调用,也常用于设置默认值、安全访问可能为None的对象和条件执行。需要注意,and返回第一个假值或最后一个真值,or返回第一个真值或最后一个假值,not始终返回True或False。
  1. def left_false():
  2.     print('左边函数执行了')
  3.     return False
  4. def right_not_executed():
  5.     print('右边函数执行了')
  6.     return True
  7. result = left_false() and right_not_executed()
  8. # 只输出:左边函数执行了
  9. def left_true():
  10.     print('左边函数执行了')
  11.     return True
  12. def right_false_not_executed():
  13.     print('右边函数执行了')
  14.     return False
  15. result = left_true() or right_false_not_executed()
  16. # 只输出:左边函数执行了
  17. name = ''
  18. display_name = name or '匿名用户'
  19. print(display_name)  # 匿名用户
  20. user = None
  21. user_name = user and user.name
  22. print(user_name)  # None
  23. response = {'data': {'user': {'name': '小明'}}}
  24. name = response and response.get('data') and response['data'].get('user') and response['data']['user'].get('name')
  25. print(name)  # 小明
  26. print(1 and 2)  # 2
  27. print(0 and 1)  # 0
  28. print(1 and 0)  # 0
  29. print([] and [1, 2])  # []
  30. print(1 or 2)  # 1
  31. print(0 or 1)  # 1
  32. print(0 or [] or {})  # {}
  33. print([] or [1, 2])  # [1, 2]
  34. print(not 1)  # False
  35. print(not 0)  # True
复制代码
直接写user.name时,如果user为None会触发AttributeError;用user and user.name可借助短路返回None。但也要注意,and/or返回的是操作对象本身,不一定严格是bool,需要纯布尔值时可用bool(...)转换。

五、成员运算符、身份运算符与优先级
in/not in用于成员判断。字典的in检查键而不是值,检查值要显式用values()。is/is not比较对象身份,==比较值;判断None应使用is None。布尔运算优先级从高到低为not、and、or,复杂表达式建议加括号提升可读性。
  1. fruits = ['苹果', '香蕉', '橘子']
  2. print('苹果' in fruits)  # True
  3. text = 'Hello, Python!'
  4. print('Python' in text)  # True
  5. user = {'name': '小明', 'age': 25}
  6. print('name' in user)  # True
  7. print('小明' in user)  # False,检查的是键
  8. print('小明' in user.values())  # True
  9. a = [1, 2, 3]
  10. b = [1, 2, 3]
  11. c = a
  12. print(a == b)  # True
  13. print(a is b)  # False
  14. print(a is c)  # True
  15. result = None
  16. if result is None:
  17.     print('没有结果')
  18. flag = True
  19. if flag:
  20.     print('flag为True')
  21. result1 = True or False and False
  22. result2 = True or (False and False)
  23. print(result1)  # True
  24. print(result2)  # True
  25. result3 = (True or False) and False
  26. print(result3)  # False
复制代码

六、三元表达式、any/all与业务规则
三元表达式语法是true_value if condition else false_value,适合简短条件选择;复杂逻辑仍应使用常规if-else。any()在任意元素为真时返回True,all()在所有元素为真时返回True;空可迭代对象中all([])为True,any([])为False。这两个函数适合批量校验字段和权限。
  1. age = 20
  2. status = '成年' if age >= 18 else '未成年'
  3. print(status)  # 成年
  4. score = 85
  5. grade = '优秀' if score >= 90 else ('良好' if score >= 80 else ('及格' if score >= 60 else '不及格'))
  6. print(grade)  # 良好
  7. numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  8. labels = ['偶数' if n % 2 == 0 else '奇数' for n in numbers]
  9. print(labels)
  10. def get_discount(is_vip):
  11.     return 0.2 if is_vip else 0.0
  12. print(get_discount(True))  # 0.2
  13. print(get_discount(False))  # 0.0
  14. print(all([True, True, True]))  # True
  15. print(all([True, False, True]))  # False
  16. print(all([]))  # True
  17. print(any([False, False, True]))  # True
  18. print(any([]))  # False
  19. def is_valid_user(user):
  20.     required_fields = ['name', 'email', 'password']
  21.     return all(user.get(field) for field in required_fields)
  22. user1 = {'name': '小明', 'email': 'xiao@example.com', 'password': '123456'}
  23. user2 = {'name': '小红', 'email': '', 'password': 'abcdef'}
  24. print(is_valid_user(user1))  # True
  25. print(is_valid_user(user2))  # False
  26. def has_admin_access(user):
  27.     roles = user.get('roles', [])
  28.     return any(role == 'admin' for role in roles)
  29. user = {'name': '小明', 'roles': ['user', 'editor']}
  30. print(has_admin_access(user))  # False
复制代码

七、实战Order类
原文用Order类演示布尔逻辑在业务规则中的应用。构造参数包括amount金额、user_vip是否VIP、has_coupon是否有优惠券、is_first_order是否首单、payment_method支付方式;payment_method在示例中只保存,不参与计算。can_use_coupon的条件是“有券且(VIP或首单或金额>=100)”;get_shipping_fee在VIP、金额>=99或首单时免运费,否则10元;calculate_final_price按VIP九折、首单满50减10计算,并用max(final, 0)避免负价。
  1. class Order:
  2.     '''订单类:演示布尔逻辑在业务规则中的应用'''
  3.     def __init__(self, amount, user_vip=False, has_coupon=False,
  4.                  is_first_order=False, payment_method='alipay'):
  5.         self.amount = amount
  6.         self.user_vip = user_vip
  7.         self.has_coupon = has_coupon
  8.         self.is_first_order = is_first_order
  9.         self.payment_method = payment_method
  10.     def can_use_coupon(self):
  11.         '''优惠券使用条件:有券 且(VIP 或 首次下单 或 金额>=100)'''
  12.         return self.has_coupon and (
  13.             self.user_vip or self.is_first_order or self.amount >= 100
  14.         )
  15.     def get_shipping_fee(self):
  16.         '''免运费条件:VIP 或 金额>=99 或 首次下单'''
  17.         if self.user_vip or self.amount >= 99 or self.is_first_order:
  18.             return 0.0
  19.         return 10.0
  20.     def calculate_final_price(self):
  21.         discount = 0.0
  22.         if self.user_vip:
  23.             discount += self.amount * 0.1
  24.         if self.is_first_order and self.amount >= 50:
  25.             discount += 10
  26.         final = self.amount - discount + self.get_shipping_fee()
  27.         return max(final, 0)
  28. order1 = Order(150, user_vip=True, has_coupon=True)
  29. print(f'订单1 可用优惠券:{order1.can_use_coupon()}')
  30. print(f'订单1 运费:{order1.get_shipping_fee()}元')
  31. print(f'订单1 最终价格:{order1.calculate_final_price():.2f}元')
复制代码

八、常见错误与适用场景
布尔逻辑的常见错误包括:把bool('False')、bool('0')误认为False;混用==与is,例如True==1为True但True is 1为False;对可能为None的对象直接取属性导致AttributeError;在字典中用in检查值时忘了values();复杂表达式依赖not、and、or优先级导致可读性差。排查时先确认对象真值,再检查短路是否导致右侧未执行,最后用括号明确逻辑分组。性能方面,短路求值可减少不必要的函数调用和属性访问;兼容性方面,bool继承int是历史设计,Python 3中不同类型比较更严格。适用场景包括表单字段校验、权限判断、订单优惠规则、配置默认值、条件执行和空容器判断;原则仍是可读性优先,复杂布尔表达式多用括号。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-19 13:01 , Processed in 0.029743 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部