Python: 布尔逻辑
第03课我们学了运算符,其中逻辑运算符
and、or、not只是匆匆带过。这一课咱们专门来搞定"是非判断"——计算机科学中最基础也最重要的概念。布尔逻辑是所有条件判断、循环控制、权限检查的根基。
1. 布尔值:True 和 False
布尔值只有两个:True(真)和 False(假)。它们是以英国数学家乔治·布尔(George Boole)命名的,他创立了布尔代数——也就是现代计算机"0 和 1"的理论基础。
print(True) # 输出 True
print(False) # 输出 False
print(type(True)) # <class 'bool'>
比较运算符的结果就是布尔值:
print(5 > 3) # True
print(10 == 5) # False
print(7 <= 7) # True
print(3 != 3) # False
(1) 布尔值也是数字
在 Python 里,True 和 False 其实是 int 的子类——True 相当于 1,False 相当于 0:
print(True + True) # 2(True=1,两个True加起来=2)
print(True * 10) # 10
print(False * 100) # 0
True == 1 和 False == 0 在 Python 中成立(所以 True + True 等于 2),但永远不要这样用。布尔值的意义在于逻辑判断,不是算术。写出 score + True 这样的代码,会让读你代码的人一脸问号。
▶ 示例:体检结果判断(难度⭐)
# 用比较运算符生成布尔值
age = 25
height = 175
weight = 70
is_adult = age >= 18 # True(成年了)
is_tall = height > 170 # True(算高的)
is_heavy = weight > 80 # False(没超80kg)
print(f"是否成年:{is_adult}")
print(f"是否高个子:{is_tall}")
print(f"是否超重:{is_heavy}")
# 直接输出布尔值——它是"值"而不是"文字"
print(f"成年 + 高个子 = {is_adult and is_tall}")
运行结果:
是否成年:True
是否高个子:True
是否超重:False
成年 + 高个子 = True
2. not:取反
not 的意思就是"反过来"——黑的变白,白的变黑。
print(not True) # False
print(not False) # True
print(not (5 > 3)) # False(5>3 是 True,取反为 False)
not 在实际编程中最常用的场景有两个:
场景一:检查"不满足条件"
# 不是管理员就不能进后台
is_admin = False
if not is_admin:
print("您没有管理员权限,无法访问。")
# 输出:您没有管理员权限,无法访问。
场景二:检查变量是否为空
# 检查用户是否没有提供名字
username = ""
if not username:
print("用户名不能为空!")
# 输出:用户名不能为空!
这里有一个 Python 中"隐式布尔转换"的小秘密——空字符串 "" 在条件判断中等价于 False。所以 not username 在 username 为空字符串时就是 True。后面会详细介绍哪些值是"假"的。
not 读作"非"或"取反"。在实际代码中,if not is_admin: 读作"如果不是管理员"。
3. and:全真才真
and 的意思是"并且"——左右两个条件都成立,结果才是 True。任何一个不成立,结果就是 False。
| 左 | 右 | 结果 |
|---|---|---|
| True | True | True |
| True | False | False |
| False | True | False |
| False | False | False |
age = 22
has_id = True
# 两个条件都要满足
can_buy_alcohol = age >= 18 and has_id
print(can_buy_alcohol) # True(既成年又有证件)
# 换个场景:申请信用卡需要年收入 >= 5万 并且 信用分 >= 600
income = 8 # 万元
credit_score = 650
qualified = income >= 5 and credit_score >= 600
print(f"信用卡申请结果:{qualified}") # True
▶ 示例:登录检查(难度⭐)
# 模拟登录检查——用户名正确且密码正确才能登录
username_correct = True
password_correct = False
can_login = username_correct and password_correct
print(f"登录结果:{can_login}") # False——密码错了
# 再加一层:需要账号未被锁定
account_locked = True
can_login = username_correct and password_correct and not account_locked
print(f"最终结果:{can_login}") # False——账号被锁定了
运行结果:
登录结果:False
最终结果:False
4. or:一真即真
or 的意思是"或者"——左右两个条件只要有一个成立,结果就是 True。只有两个都不成立才是 False。
| 左 | 右 | 结果 |
|---|---|---|
| True | True | True |
| True | False | True |
| False | True | True |
| False | False | False |
# 周末或节假日都可以休息
is_weekend = True
is_holiday = False
can_rest = is_weekend or is_holiday
print(can_rest) # True(虽然是周末)
# 地铁安检:带水或者带饮料都需要检查
has_water = True
has_drink = False
need_check = has_water or has_drink
print(f"需要安检:{need_check}") # True
(1) 练习:完整的真值表验证
# 用代码验证真值表——and 和 or 的所有组合
a = True
b = True
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
a = True
b = False
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
a = False
b = True
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
a = False
b = False
print(f"{a} and {b} = {a and b}")
print(f"{a} or {b} = {a or b}")
运行结果:
True and True = True
True or True = True
True and False = False
True or False = True
False and True = False
False or True = True
False and False = False
False or False = False
5. 短路求值
这一点在第03课提过,但太重要了,我们再深入看一下。Python 的逻辑运算符在得出最终结果后会立刻停止计算,不再执行剩余的表达式。
(1) and 的短路:左边 False → 右边不执行
def check_right():
print("→ check_right 被调用了!")
return True
print("False and check_right():")
result = False and check_right() # check_right 根本不会执行
print(f"结果:{result}\n")
print("True and check_right():")
result = True and check_right() # check_right 会执行
print(f"结果:{result}")
运行结果:
False and check_right():
结果:False
True and check_right():
→ check_right 被调用了!
结果:True
(2) or 的短路:左边 True → 右边不执行
print("True or check_right():")
result = True or check_right() # check_right 不会执行
print(f"结果:{result}")
(3) 短路求值的经典用法
1. 安全访问:防止 None 报错
# 假设 user 可能是 None(表示用户不存在)
user = None
# user.get("name") 会报错——None 没有 get 方法
# 用短路来保护:
name = user and user.get("name")
print(name) # None——user 是假值,短路了,没执行 user.get()
# 如果用户存在:
user = {"name": "Charlie"}
name = user and user.get("name")
print(name) # Charlie
2. 设置默认值
# 如果用户没输入名字,就用默认值
user_input = "" # 空字符串(假值)
name = user_input or "游客"
print(f"欢迎你,{name}") # 欢迎你,游客
user_input = "Alice"
name = user_input or "游客"
print(f"欢迎你,{name}") # 欢迎你,Alice
user_input or "默认值" 这种写法非常 Pythonic——左边是假值(空字符串)时取右边,是真值(有内容)时取左边。它本质上就是在利用 or 的短路特性。
6. 真值与假值
在 Python 中,任何值都可以当作布尔值来用。在条件判断中,某些值被视为"假"(falsy),其他所有值都是"真"(truthy)。
(1) 常见的假值
# Python 中以下值在条件判断中等价于 False
print(bool(False)) # False——布尔假
print(bool(0)) # False——数字零
print(bool(0.0)) # False——浮点数零
print(bool("")) # False——空字符串
print(bool([])) # False——空列表(后面会学)
print(bool(None)) # False——空值
其他的值都是真值:
print(bool(1)) # True——非零数字
print(bool(-5)) # True——负数也是真值!
print(bool("Python")) # True——非空字符串
print(bool(" ")) # True——空格也是字符,非空就是真
print(bool([1, 2])) # True——非空列表
-5 和 " "(空格)都是真值,这可能会出乎你的意料。-5 是非零整数,所以它是真;空格是一个字符,字符串非空,所以它是真。只有空字符串 "" 才是假。
(2) 利用真值简化代码
# 不推荐(啰嗦)
name = "Charlie"
if name != "":
print(f"你好,{name}")
# 推荐(简洁)
name = "Charlie"
if name:
print(f"你好,{name}")
# 不推荐
score = 85
if score != 0:
print(f"得分:{score}")
# 推荐
score = 85
if score:
print(f"得分:{score}")
if name: 比 if name != "": 更"Python 风格"。但要注意不要滥用——if score: 在 score=0 时不会执行,如果你确实需要区分"0分"和"没分数",还是要用 is not None。
7. is 和 is not:身份比较
is 比较两个变量是否指向同一个对象(内存中的同一块空间),而不是比较它们的值是否相等。第03课提过,这里用更多例子来巩固。
# == 比较值,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,指向同一个列表
# 小整数缓存(Python 内部优化)
x = 256
y = 256
print(x is y) # 可能是 True——小整数被缓存了
x = 1000
y = 1000
print(x is y) # 可能是 False——大整数没有被缓存
is 来比较整数或字符串的值。虽然小整数因为 Python 内部优化有时 is 返回 True,但这是实现细节,不可靠。判断值相等永远用 ==。
(1) 最正确的用法:判断 None
Python 社区有一个约定俗成的规则——判断一个值是不是 None,永远用 is,不用 ==:
# ✅ 正确做法
result = None
if result is None:
print("没有结果")
# ❌ 不推荐
if result == None:
print("没有结果")
▶ 示例:注册条件组合判断(难度⭐⭐)
# 注册时需要同时满足多个条件
username = "alice2026"
password = "abc123"
age = 20
agreed_terms = True
# 用户名不为空 且 密码长度>=6 且 已成年 且 同意条款
is_valid = (
bool(username) and
len(password) >= 6 and
age >= 18 and
agreed_terms
)
# 用 or 给出具体的失败原因
reason = (
(not username and "用户名为空") or
(len(password) < 6 and "密码太短") or
(age < 18 and "未成年") or
(not agreed_terms and "未同意条款") or
"注册成功"
)
print(f"注册结果:{is_valid}")
print(f"原因:{reason}")
# 换一个不满足的场景
age = 16
is_valid2 = bool(username) and len(password) >= 6 and age >= 18 and agreed_terms
reason2 = (
(not username and "用户名为空") or
(len(password) < 6 and "密码太短") or
(age < 18 and "未成年") or
(not agreed_terms and "未同意条款") or
"注册成功"
)
print(f"注册结果:{is_valid2}")
print(f"原因:{reason2}")
输出:
注册结果:True
原因:注册成功
注册结果:False
原因:未成年
8. 常见应用场景
- 权限控制:
is_admin or (is_logged_in and has_permission)——组合多个条件决定用户能做什么。 - 输入验证:
username and password——检查用户是否同时提供了用户名和密码。 - 可选参数默认值:
timeout or 30——如果没设置超时时间,就用默认 30 秒。 - 安全访问链:
user and user.address and user.address.city——逐层安全访问,中间任何一步是假值就短路。 - 开关控制:
is_enabled and is_connected——两个条件都满足才允许操作。
❓ 常见问题
True 和 "True" 有什么区别?True(不带引号)是布尔值,"True"(带引号)是字符串。它们不是同一个东西:type(True) 是 <class 'bool'>,type("True") 是 <class 'str'>。在条件判断中,if "True": 永远是 True(因为非空字符串是真值),if "False": 也永远是 True(同样因为非空)。所以在写条件判断时,千万不要给布尔值加引号。is 和 == 到底该用哪个?==。is 只在一个场景是惯例——判断 None:if result is None:。其他所有值比较都用 ==。记住:== 比"值",is 比"身份"。not not "hello" 结果是 True?not "hello" 先把 "hello" 当成布尔值(非空字符串是真值),取反得到 False。然后 not not "hello" 再对 False 取反,得到 True。所以 not not x 就相当于 bool(x)——把 x 转成布尔值。但这种写法不常见,直接用 bool(x) 更清晰。📖 小节
- 布尔值只有两个:
True和False,它们其实是int的子类(True=1、False=0),但不要拿来做算术 not取反:真变假,假变真and全真才真:左右都True才返回Trueor一真即真:只要有一个True就返回True- Python 中假值包括:
False、0、0.0、""、[]、None——其他都是真值 - 短路求值:
and左边假 → 右边不执行;or左边真 → 右边不执行 - 利用短路可以实现"安全访问"和"默认值"两种经典写法
is比较身份,==比较值;判断None时用is
📝 作业
-
基础题(难度⭐):给出以下表达式的值,先猜再验证:
not (10 > 5)True and False or Truenot False and True(5 > 3) or (2 > 10) and (8 == 8)——提示:注意优先级,and比or高
-
进阶题(难度⭐⭐):写一段代码,检测用户输入的字符串。要求:
- 如果用户输入为空,输出"输入不能为空"
- 如果用户输入全是空格,也视为"输入不能为空"(提示:可以用
strip()方法去掉空格再判断) - 如果用户输入长度小于 6,输出"输入长度至少 6 个字符"
- 否则输出"输入有效"
-
挑战题(难度⭐⭐⭐):写一个"三位数特征判断"程序。给定一个三位数
num(如 153),判断它:- 是不是偶数(用
%取余) - 是不是能同时被 3 和 5 整除
- 是不是"回文数"(百位和个位相同,如 121、353)
- 以上三个条件中满足几个?输出满足条件的个数
所有判断使用布尔表达式完成,不要用 if 语句(留到下一课)。
- 是不是偶数(用