在Python脚本中,条件分支、循环控制和业务规则几乎都依赖布尔判断。bool只有True和False两个值,但真值测试、比较运算、逻辑运算和短路求值有不少细节。原文围绕这些点给出了示例,下面按代码实现、参数含义、错误原因和业务场景重组说明。
一、True/False字面量与bool/int关系
Python布尔字面量首字母必须大写,true和false只是普通变量名,没有布尔含义。bool是int的子类,因此True==1、False==0成立,True+True为2;但True is 1为False,二者不是同一对象。原文示例:- is_active = True
- is_deleted = False
- print(type(True)) # <class 'bool'>
- print(isinstance(True, int)) # True
- print(True == 1) # True
- print(False == 0) # True
- print(True + True) # 2
- print(True * 10) # 10
- print(bool.__bases__) # (<class 'int'>,)
- print(issubclass(bool, int)) # True
- scores = [True, False, True, True]
- print(sum(scores)) # 3
- print(True == 1) # True
- 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。- print(bool(None)) # False
- print(bool(0)) # False
- print(bool('')) # False
- print(bool([])) # False
- print(bool({})) # False
- print(bool(())) # False
- print(bool(set())) # False
- print(bool(range(0))) # False
- print(bool('False')) # True
- print(bool('0')) # True
- print(bool(' ')) # True
- print(bool([0])) # True
- print(bool([None])) # True
- print(bool({False: True})) # True
- print(bool(-1)) # True
复制代码 自定义对象可通过__bool__控制真值;没有__bool__时,Python会尝试__len__,返回0为False,否则为True。例如用户对象按is_active判断,购物车按items长度判断:- class User:
- def __init__(self, name, is_active=True):
- self.name = name
- self.is_active = is_active
- def __bool__(self):
- '''自定义真值判断:只有活跃用户才是True'''
- return self.is_active
- active_user = User('小明', True)
- inactive_user = User('小红', False)
- print(bool(active_user)) # True
- print(bool(inactive_user)) # False
- class ShoppingCart:
- def __init__(self):
- self.items = []
- def add(self, item):
- self.items.append(item)
- def __len__(self):
- '''定义len()的行为'''
- return len(self.items)
- cart = ShoppingCart()
- print(bool(cart)) # False
- cart.add('Python编程书')
- print(bool(cart)) # True
复制代码
三、比较运算与链式比较
Python支持==、!=、<、>、<=、>=六种比较运算,也支持数学式链式比较。链式比较会按and逻辑执行,但中间对象只计算一次。不同数字类型可比较,例如5==5.0、5==5+0j;字符串按Unicode码点比较;Python 3中很多不同类型不能直接用<比较,会抛出TypeError。- x, y = 10, 20
- print(x == y) # False
- print(x != y) # True
- print(x < y) # True
- print(x > y) # False
- print(x <= y) # True
- print(x >= y) # False
- age = 25
- print(18 <= age <= 30) # True
- print(18 <= age and age <= 30) # True
- a, b, c, d = 1, 2, 2, 3
- print(a < b == c < d) # True
- print(5 == 5.0) # True
- print(5 == 5 + 0j) # True
- print(5 == True) # True,但不要依赖
- print('apple' < 'banana') # True
- print('a' < 'A') # False
- # print('hello' < 5) # TypeError
- # print([1, 2] < (1, 2)) # TypeError
复制代码
四、逻辑运算、短路求值与返回值
and、or、not是Python的逻辑运算符。and左侧为假时不再计算右侧,or左侧为真时不再计算右侧,这就是短路求值。它可用于避免不必要的函数调用,也常用于设置默认值、安全访问可能为None的对象和条件执行。需要注意,and返回第一个假值或最后一个真值,or返回第一个真值或最后一个假值,not始终返回True或False。- def left_false():
- print('左边函数执行了')
- return False
- def right_not_executed():
- print('右边函数执行了')
- return True
- result = left_false() and right_not_executed()
- # 只输出:左边函数执行了
- def left_true():
- print('左边函数执行了')
- return True
- def right_false_not_executed():
- print('右边函数执行了')
- return False
- result = left_true() or right_false_not_executed()
- # 只输出:左边函数执行了
- name = ''
- display_name = name or '匿名用户'
- print(display_name) # 匿名用户
- user = None
- user_name = user and user.name
- print(user_name) # None
- response = {'data': {'user': {'name': '小明'}}}
- name = response and response.get('data') and response['data'].get('user') and response['data']['user'].get('name')
- print(name) # 小明
- print(1 and 2) # 2
- print(0 and 1) # 0
- print(1 and 0) # 0
- print([] and [1, 2]) # []
- print(1 or 2) # 1
- print(0 or 1) # 1
- print(0 or [] or {}) # {}
- print([] or [1, 2]) # [1, 2]
- print(not 1) # False
- 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,复杂表达式建议加括号提升可读性。- fruits = ['苹果', '香蕉', '橘子']
- print('苹果' in fruits) # True
- text = 'Hello, Python!'
- print('Python' in text) # True
- user = {'name': '小明', 'age': 25}
- print('name' in user) # True
- print('小明' in user) # False,检查的是键
- print('小明' in user.values()) # True
- a = [1, 2, 3]
- b = [1, 2, 3]
- c = a
- print(a == b) # True
- print(a is b) # False
- print(a is c) # True
- result = None
- if result is None:
- print('没有结果')
- flag = True
- if flag:
- print('flag为True')
- result1 = True or False and False
- result2 = True or (False and False)
- print(result1) # True
- print(result2) # True
- result3 = (True or False) and False
- print(result3) # False
复制代码
六、三元表达式、any/all与业务规则
三元表达式语法是true_value if condition else false_value,适合简短条件选择;复杂逻辑仍应使用常规if-else。any()在任意元素为真时返回True,all()在所有元素为真时返回True;空可迭代对象中all([])为True,any([])为False。这两个函数适合批量校验字段和权限。- age = 20
- status = '成年' if age >= 18 else '未成年'
- print(status) # 成年
- score = 85
- grade = '优秀' if score >= 90 else ('良好' if score >= 80 else ('及格' if score >= 60 else '不及格'))
- print(grade) # 良好
- numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- labels = ['偶数' if n % 2 == 0 else '奇数' for n in numbers]
- print(labels)
- def get_discount(is_vip):
- return 0.2 if is_vip else 0.0
- print(get_discount(True)) # 0.2
- print(get_discount(False)) # 0.0
- print(all([True, True, True])) # True
- print(all([True, False, True])) # False
- print(all([])) # True
- print(any([False, False, True])) # True
- print(any([])) # False
- def is_valid_user(user):
- required_fields = ['name', 'email', 'password']
- return all(user.get(field) for field in required_fields)
- user1 = {'name': '小明', 'email': 'xiao@example.com', 'password': '123456'}
- user2 = {'name': '小红', 'email': '', 'password': 'abcdef'}
- print(is_valid_user(user1)) # True
- print(is_valid_user(user2)) # False
- def has_admin_access(user):
- roles = user.get('roles', [])
- return any(role == 'admin' for role in roles)
- user = {'name': '小明', 'roles': ['user', 'editor']}
- 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)避免负价。- class Order:
- '''订单类:演示布尔逻辑在业务规则中的应用'''
- def __init__(self, amount, user_vip=False, has_coupon=False,
- is_first_order=False, payment_method='alipay'):
- self.amount = amount
- self.user_vip = user_vip
- self.has_coupon = has_coupon
- self.is_first_order = is_first_order
- self.payment_method = payment_method
- def can_use_coupon(self):
- '''优惠券使用条件:有券 且(VIP 或 首次下单 或 金额>=100)'''
- return self.has_coupon and (
- self.user_vip or self.is_first_order or self.amount >= 100
- )
- def get_shipping_fee(self):
- '''免运费条件:VIP 或 金额>=99 或 首次下单'''
- if self.user_vip or self.amount >= 99 or self.is_first_order:
- return 0.0
- return 10.0
- def calculate_final_price(self):
- discount = 0.0
- if self.user_vip:
- discount += self.amount * 0.1
- if self.is_first_order and self.amount >= 50:
- discount += 10
- final = self.amount - discount + self.get_shipping_fee()
- return max(final, 0)
- order1 = Order(150, user_vip=True, has_coupon=True)
- print(f'订单1 可用优惠券:{order1.can_use_coupon()}')
- print(f'订单1 运费:{order1.get_shipping_fee()}元')
- 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中不同类型比较更严格。适用场景包括表单字段校验、权限判断、订单优惠规则、配置默认值、条件执行和空容器判断;原则仍是可读性优先,复杂布尔表达式多用括号。 |