一、开篇:程序中的"是"与"否"
在现实世界中,我们每天都在做判断:"今天下雨了吗?"→是/否,"这个商品打折吗?"→是/否,"用户登录了吗?"→是/否。
在编程世界中,这种"是/否"的判断用**布尔类型(bool)**来表示。布尔类型只有两个值:true(是)和false(否)。别看它简单——程序里几乎所有的条件判断、循环控制、逻辑推理,都建立在这两个值之上。
这一篇我们就来彻底搞懂布尔类型,以及与之密切相关的逻辑运算。你会发现,python的布尔逻辑有一些特别有趣的设计。
二、布尔类型基础
2.1 true和false
# 布尔字面量(注意首字母大写) is_active = true is_deleted = false print(type(true)) # <class 'bool'> print(type(false)) # <class 'bool'> # bool是int的子类!这是python的一个有趣设计 print(isinstance(true, int)) # true print(true == 1) # true print(false == 0) # true print(true + true) # 2(因为true等于1) print(true * 10) # 10
python中的 true 和 false 首字母必须大写。true 和 false(全小写)在python中只是普通变量名,没有特殊含义。这是python和很多其他语言(javascript、java)的一个重要区别。
2.2 bool是int的子类
这个设计很有历史渊源——python早期版本中没有独立的bool类型,用整数1和0代表真和假。后来加入了bool类型,但为了向后兼容,让bool继承了int:
# bool继承自int的证据 print(bool.__bases__) # (<class 'int'>,) print(issubclass(bool, int)) # true # 这带来的有趣效果 scores = [true, false, true, true] print(sum(scores)) # 3(true当作1,false当作0) # 但这意味着你要小心 print(isinstance(true, int)) # true(技术上正确,但可能让人困惑) print(true == 1) # true print(true is 1) # false(true和1是不同的对象)
日常使用中,你基本不需要关心"bool继承自int"这个事实。把true/false当作纯粹的布尔值来使用就好。
三、真值测试——哪些值被视为true或false
3.1 python的真值规则
在python中,每个对象都有一个"真值"——也就是说,任何值放在 if 或 while 的条件位置时,python都能判断它是true还是false。
被视为 false 的值(称为"假值"或"falsy")只有以下几类:
# python中所有的"假值"
bool(none) # false — none
bool(false) # false — false自身
bool(0) # false — 整数0
bool(0.0) # false — 浮点数0.0
bool(0j) # false — 复数0
bool('') # false — 空字符串
bool([]) # false — 空列表
bool({}) # false — 空字典
bool(()) # false — 空元组
bool(set()) # false — 空集合
bool(range(0)) # false — 空的range
除此之外,其他所有值都是 true:
# 这些全是true
bool(1) # true
bool(-1) # true(包括负数!)
bool(0.1) # true
bool(' ') # true(含空格的字符串不是空字符串)
bool('false') # true(注意:字符串'false'的bool值是true!)
bool([0]) # true(含有一个元素的列表)
bool([none]) # true
bool({false: true}) # true
常见误解:
bool('false')→true!因为字符串'false'不是空字符串bool('0')→true!同理bool([[]])→true!列表非空(里面有一个空列表)- 负数也是true:
bool(-1)→true
3.2 自定义对象的真值
你可以通过定义 __bool__ 或 __len__ 方法来控制自定义对象的真值:
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
if active_user:
print(f'{active_user.name}是活跃用户')
if not inactive_user:
print(f'{inactive_user.name}不是活跃用户')
class shoppingcart:
def __init__(self):
self.items = []
def add(self, item):
self.items.append(item)
def __len__(self):
"""定义len()的行为"""
return len(self.items)
# 没有定义__bool__时,python会尝试调用__len__()
# 如果__len__()返回0,对象为false;否则为true
cart = shoppingcart()
print(bool(cart)) # false(购物车是空的)
cart.add('python编程书')
print(bool(cart)) # true(购物车里有东西)
四、比较运算符
4.1 六种比较运算
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 — 大于等于
4.2 链式比较
python支持数学中常见的链式比较,这是很多语言不具备的优雅特性:
age = 25 # python的链式比较——和数学写法一样 print(18 <= age <= 30) # true(age在18到30之间) print(0 < age < 100) # true # 等价于 print(18 <= age and age <= 30) # true # 链式比较的内部执行逻辑 # 18 <= age <= 30 # python将其解释为:(18 <= age) and (age <= 30) # 但age只计算一次! # 任意长度的链式比较 a, b, c, d = 1, 2, 2, 3 print(a < b == c < d) # true(1 < 2 且 2 == 2 且 2 < 3)
4.3 不同类型之间的比较
# 数字类型之间可以比较
print(5 == 5.0) # true
print(5 == 5 + 0j) # true
print(5 == true) # true(但不要依赖这个!)
# 字符串之间可以比较(按字典序/unicode码点)
print('apple' < 'banana') # true
print('a' < 'a') # false(小写字母的码点大于大写字母)
# 不同类型之间——python 3中很多不能比较
# print('hello' < 5) # typeerror: '<' not supported
# print([1, 2] < (1, 2)) # typeerror
五、逻辑运算符
5.1 and、or、not
这三个是python的逻辑运算符,和大多数语言一样:
# and:两者都为true结果才为true print(true and true) # true print(true and false) # false print(false and true) # false print(false and false) # false # or:任意一个为true结果就为true print(true or true) # true print(true or false) # true print(false or true) # true print(false or false) # false # not:取反 print(not true) # false print(not false) # true
5.2 短路求值
python的逻辑运算符使用短路求值(short-circuit evaluation),这是一个非常高效且有用的设计:
# and的短路:如果左边为false,右边不再计算
def left_false():
print('左边函数执行了')
return false
def right_not_executed():
print('右边函数执行了')
return true
result = left_false() and right_not_executed()
# 输出:
# 左边函数执行了
# (右边函数不会执行!因为左边已经是false了)
# or的短路:如果左边为true,右边不再计算
def left_true():
print('左边函数执行了')
return true
def right_not_executed():
print('右边函数执行了')
return false
result = left_true() or right_not_executed()
# 输出:
# 左边函数执行了
# (右边函数不会执行!因为左边已经是true了)
5.3 短路求值的实用技巧
# 技巧一:设置默认值
name = ''
display_name = name or '匿名用户'
print(display_name) # 匿名用户
# 技巧二:安全访问可能为none的对象
user = none
# user_name = user.name # attributeerror!
user_name = user and user.name # 安全:返回none而不是报错
print(user_name) # none
# 技巧三:链式安全访问
response = {'data': {'user': {'name': '小明'}}}
# 如果response['data']不存在,这里会崩溃
# print(response['data']['user']['name'])
# 安全的做法
name = response and response.get('data') and response['data'].get('user') and response['data']['user'].get('name')
print(name) # 小明
# 技巧四:条件执行
should_log = true
should_log and print('这条日志被记录了') # 打印
should_log = false
should_log and print('这条日志不会被记录') # 不打印
5.4 and和or的返回值
和很多语言不同,python的 and 和 or 不总是返回 true 或 false:
# and返回第一个假值,或最后一个真值
print(1 and 2) # 2(两个都为真,返回最后一个)
print(0 and 1) # 0(第一个就是假值,返回它)
print(1 and 0) # 0(第二个是假值,返回它)
print([] and [1, 2]) # [](第一个假值)
# or返回第一个真值,或最后一个假值
print(1 or 2) # 1(第一个就是真值,返回它)
print(0 or 1) # 1(第一个假值,返回第二个真值)
print(0 or [] or {}) # {}(全是假值,返回最后一个)
print([] or [1, 2]) # [1, 2](第一个真值)
# not始终返回true或false
print(not 1) # false
print(not 0) # true
print(not []) # true
这个特性让python的and/or非常灵活。上面提到的"设置默认值"语法(value = name or '默认')就是利用了这个特性。
六、成员运算符和身份运算符
6.1 成员运算符 in / not in
# in:判断元素是否在容器中
fruits = ['苹果', '香蕉', '橘子']
print('苹果' in fruits) # true
print('葡萄' in fruits) # false
print('葡萄' not in fruits) # true
# 在字符串中
text = 'hello, python!'
print('python' in text) # true
print('java' not in text) # true
# 在字典中(检查键而不是值)
user = {'name': '小明', 'age': 25}
print('name' in user) # true
print('小明' in user) # false(检查的是键!)
print('小明' in user.values()) # true(明确检查值)
# 在集合中
numbers = {1, 2, 3, 4, 5}
print(3 in numbers) # true
6.2 身份运算符 is / is not
# is:判断两个变量是否指向同一个对象(内存地址相同)
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # true(值相等)
print(a is b) # false(不是同一个对象)
print(a is c) # true(c就是a,同一个对象)
print(a is not b) # true
# is 最主要的用途:判断none
result = none
if result is none:
print('没有结果')
# 另一个常见用途:判断true/false
# 不推荐用is判断true/false,用==
flag = true
# if flag is true: # 不推荐
if flag: # 推荐
print('flag为true')
is 和 == 的区别,是python面试的常见考点:
==判断值是否相等(调用__eq__方法)is判断身份是否相同(比较id())
七、布尔运算的优先级
7.1 完整优先级表
在写复杂的布尔表达式时,理解优先级很重要:
最高优先级: not (逻辑非)
and (逻辑与)
最低优先级: or (逻辑或)
7.2 优先级实例
# 由于优先级规则,这两个表达式是等价的
result1 = true or false and false
result2 = true or (false and false)
print(result1) # true
print(result2) # true
# 解释:and优先级高,先计算 false and false = false
# 然后 true or false = true
# 如果加括号改变优先级
result3 = (true or false) and false
print(result3) # false
# 混合比较和逻辑运算
age = 25
has_ticket = true
is_vip = false
# ✅ 明确使用括号
if (age >= 18 and has_ticket) or is_vip:
print('可以入场')
# ❌ 不加括号,依赖优先级——虽然能正常工作但可读性差
if age >= 18 and has_ticket or is_vip:
print('可以入场')
虽然python有明确的优先级规则,但在写复杂布尔表达式时,强烈建议使用括号来明确你的意图。括号不花钱,但读代码时的清晰度价值连城。
八、条件表达式(三元运算符)
# python的三元表达式
# 语法:true_value if condition else false_value
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
三元表达式适合简短的条件选择。如果条件逻辑很复杂,不要强行塞进三元表达式——用常规的 if-else 更清晰。
九、any() 和 all() 函数
python内置了两个非常实用的函数来对可迭代对象做批量布尔判断:
# all():所有元素都为true才返回true
print(all([true, true, true])) # true
print(all([true, false, true])) # false
print(all([1, 2, 3])) # true(所有非零,都是真值)
print(all([1, 0, 3])) # false(0是假值)
print(all([])) # true(空可迭代对象,vacuously true)
# any():任意一个元素为true就返回true
print(any([false, false, true])) # true
print(any([false, false, false])) # false
print(any([0, 0, 1])) # 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(email为空)
# 检查是否有管理员权限
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
十、实战:用布尔逻辑构建业务规则
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
# vip 9折
if self.user_vip:
discount += self.amount * 0.1
# 首次下单满50减10元
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}元')
十一、本篇小结
布尔类型虽然只有两个值,但它是程序逻辑的基石。核心要点:
- true和false:首字母大写,bool是int的子类
- 真值测试:空值(none, 0, ‘’, [], {}, ())为false,其他为true
- 逻辑运算符:
and/or有短路求值特性,返回的是操作对象本身 - 比较运算符:支持链式比较
1 <= x <= 10 - is vs ==:is比较对象身份,==比较值
- 三元表达式:
value if condition else other_value - any()和all():批量判断的最佳工具
写布尔表达式时,优先考虑可读性,多用括号。代码是写给人看的——(age >= 18 and has_ticket) or is_vip 比不加括号的版本更容易被理解。
到此这篇关于python中布尔类型bool与逻辑运算使用全解析的文章就介绍到这了,更多相关python布尔类型与逻辑运算内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论