当前位置: 首页 > news >正文

2025-10-06 Python不基础 11——if 判断

文章目录

  • 1. 四种 if 判断
    • 1.1. `if a is True`
    • 1.2. `if a == True`
    • 1.3. `if a`
    • 1.4. `if bool(a)`
  • 2. 底层实现:`PyObject_IsTrue`
    • 2.1. 字节码入口:`pop_jump_if_false`
    • 2.2. 内置类型判定规则:`PyObject_IsTrue`
      • 步骤1:直接判断`True/False/None`
      • 步骤2:判断是否为“数字类型”(Number)
      • 步骤3:判断是否为“映射类型”(Mapping)
      • 步骤4:判断是否为“序列类型”(Sequence)
    • 2.3. 自定义类型真值判定规则
  • 3. `bool(a)`:类的实例化
  • 4. 如何正确使用 if
    • 4.1. 优先“明确判断”,减少“模糊判断”
    • 4.2. 压缩变量的类型范围
    • 4.3. 避免滥用`a == True`和`a is True`

本文参考视频链接:

  • https://www.bilibili.com/video/BV1dZ4y127fR

1. 四种 if 判断

以变量a为例,对比四种if判断形式的行为差异,核心是明确“判断的是变量本身”还是“变量的真值属性”。

先看基础代码示例,当a=Truea=False时的表现:

a = True  # 或 a = False# 四种判断形式
if a is True:print("True 1")
if a == True:print("True 2")
if a:print("True 3")
if bool(a):print("True 4")
  • a=True:4个if均成立,打印“True 1/2/3/4”;
  • a=False:所有if均不成立,无输出。

但当a不是True/False时,四种判断的差异会完全显现。

image-20251006140540237

1.1. if a is True

  • 基于身份判定is比较的是变量的内存地址id()),仅当a是Python内置的True对象时,条件才成立;
  • a是任何其他值(包括1"非空字符串"[1]等“真值”),条件均不成立。
a = 1  # 1是“真值”,但不是True对象
print(a is True)  # 输出:False
a = True
print(a is True)  # 输出:True
  • 反面不是a is Falsea is True的否定是a is not True,而非a is False
    • 原因:Python中变量可能是True/False之外的值(如None0""等),这些值既不是True也不是False
    • 示例:a = Nonea is not True成立,但a is False不成立。
  • 适用场景:需精确筛选True对象的场景(极少用,仅当逻辑中必须区分“True”与其他“真值”时)。

1.2. if a == True

  • 基于值相等判定==比较的是值,且可被自定义类重载__eq__方法修改行为);
  • 对于内置类型,== True的逻辑等同于“是否为真值”(如1 == True成立,[1] == True不成立),但行为不可控。

为什么不推荐?

  • 重载风险==运算符可被自定义类通过__eq__方法重载,导致判断逻辑异常;
    • 示例:自定义类class MyObj: def __eq__(self, other): return True,则MyObj() == True会返回True,不符合预期。
  • 冗余且模糊:若想判断“真值”,直接用if a更简洁;若想判断“是否为True本身”,用a is True更精确,a == True处于两者之间,无明确场景。

1.3. if a

  • 这是Python中最常见的判断形式,本质是调用Python内部函数PyObject_IsTrue(a),根据返回值(1=真,0=假,-1=出错)判定条件是否成立;
  • 不同类型的变量,PyObject_IsTrue的判定规则不同,可分为“内置类型”和“自定义类型”两类。

1.4. if bool(a)

对比 if a

  • 逻辑等价:两者均依赖PyObject_IsTrue(a),判定结果完全一致;
  • 性能差异if bool(a)多一次bool类的实例化调用(函数调用开销),而if a直接通过字节码调用PyObject_IsTrue,更高效;
  • 适用场景
    • 若仅需判断真值:直接用if a,简洁高效;
    • 若需显式获取布尔值(如存储、传递):用bool(a),例如is_valid = bool(a)

2. 底层实现:PyObject_IsTrue

分析Python字节码和C源码,揭示if a的核心依赖——PyObject_IsTrue函数,其判定逻辑分内置类型自定义类型两类。

image-20251006140841634

2.1. 字节码入口:pop_jump_if_false

当执行if a时,Python编译后的字节码会出现pop_jump_if_false指令:

  • 作用:弹出栈顶的变量a,调用PyObject_IsTrue(a)判断;
  • 若返回0(假),则跳转到if块之外;若返回1(真),则执行if块内代码。

源码层面(CPython):pop_jump_if_false会优先检查a是否为True/False(快速路径,fast path),若不是,则调用PyObject_IsTrue(a)

2.2. 内置类型判定规则:PyObject_IsTrue

PyObject_IsTrue对内置类型的判定分4步,优先级从高到低:

image-20251006140927000

步骤1:直接判断True/False/None

  • a is True:返回1(真);
  • a is Falsea is None:返回0(假);
    • 关键结论:Noneif a中会被判定为假,这是很多新手容易忽略的点。

步骤2:判断是否为“数字类型”(Number)

  • 适用类型:intfloatcomplexdecimal.Decimal等;
  • 判定规则:非零即真,零即假
    • 示例:
      • a = 5(非零int)→ 真;a = 0.0(零float)→ 假;
      • a = 3+4j(非零complex)→ 真;a = 0+0j(零complex)→ 假。

步骤3:判断是否为“映射类型”(Mapping)

  • 适用类型:dict(字典)、set(集合)、frozenset(不可变集合)等(key-value结构或无重复元素集合);
  • 判定规则:非空即真,空即假(判断len(a) > 0);
    • 示例:
      • a = {"name": "Alice"}(非空dict)→ 真;a = {}(空dict)→ 假;
      • a = {1,2,3}(非空set)→ 真;a = set()(空set)→ 假。

步骤4:判断是否为“序列类型”(Sequence)

  • 适用类型:str(字符串)、list(列表)、tuple(元组)、range(范围)等(可数、有序结构);
  • 判定规则:非空即真,空即假(判断len(a) > 0);
    • 示例:
      • a = "hello"(非空str)→ 真;a = ""(空str)→ 假;
      • a = [1,2](非空list)→ 真;a = [](空list)→ 假;
      • a = range(5)(非空range,len=5)→ 真;a = range(0)(空range,len=0)→ 假。
类型分类判定规则真(True)示例假(False)示例
布尔/NoneTrue=真,False/None=假TrueFalse、None
数字(Number)非零=真,零=假3、-2.5、1+0j0、0.0、0+0j
映射(Mapping)非空=真,空=假{“a”:1}、{1,2}{}、set()
序列(Sequence)非空=真,空=假“hi”、[1]、(2,3)、range(1)“”、[]、()、range(0)

2.3. 自定义类型真值判定规则

a是自定义类的实例(如class MyClass: pass),PyObject_IsTrue的判定逻辑与内置类型不同,核心依赖类的两个特殊方法:__bool____len__

image-20251006141156293

判定优先级(从高到低)

  1. 检查是否定义__bool__方法

    • __bool__方法需返回布尔值(True/False);
    • 若定义,则PyObject_IsTrue直接使用该方法的返回值(返回True则判定为真,False则为假)。
  2. 若未定义__bool__,检查是否定义__len__方法

    • __len__方法需返回非负整数(长度);
    • 若定义,则PyObject_IsTrue判定规则为:len(a) > 0即真,否则为假(与序列/映射一致)。
  3. 若两者均未定义

    • PyObject_IsTrue直接返回1(真),即自定义实例默认被判定为真。
# 示例1:定义__bool__
class MyObj1:def __bool__(self):return False  # 强制返回Falsea = MyObj1()
if a:print("真")  # 不执行,因为__bool__返回False# 示例2:未定义__bool__,定义__len__
class MyObj2:def __len__(self):return 0  # 长度为0a = MyObj2()
if a:print("真")  # 不执行,因为len(a)=0# 示例3:两者均未定义
class MyObj3:passa = MyObj3()
if a:print("真")  # 执行,默认判定为真

__bool____len__的返回值会被严格检查,避免递归调用PyObject_IsTrue

image-20251006141315838
  • __bool__必须返回布尔值:若返回非布尔值(如1),Python会报错(TypeError: __bool__ should return bool, not int);
  • __len__必须返回非负整数:若返回非整数(如"abc"),Python会报错(TypeError: __len__() should return an integer);
  • 因此,__bool__/__len__的返回值可直接判定,不会再次调用PyObject_IsTrue,避免无限递归。

3. bool(a):类的实例化

bool不是函数,而是Python的内置类class bool),bool(a)本质是创建bool类的实例,其逻辑与if a完全等价。

image-20251006141632904
  • 源码层面(CPython):bool类继承自int类(class bool(int): ...),其__new__方法(实例化方法)核心调用PyObject_IsTrue(a)
  • 实例化逻辑:
    1. 调用PyObject_IsTrue(a)获取结果(1/0/-1);
    2. 若结果为1:返回Truebool类的唯一“真”实例);
    3. 若结果为0:返回Falsebool类的唯一“假”实例);
    4. 若结果为-1(出错):抛出异常。
print(type(bool))  # 输出:<class 'type'>(证明是类)
print(bool(123))   # 输出:True(PyObject_IsTrue(123)=1)
print(bool([]))    # 输出:False(PyObject_IsTrue([])=0)

4. 如何正确使用 if

视频结尾给出了关键建议,避免因“真值判定”的歧义导致bug:

4.1. 优先“明确判断”,减少“模糊判断”

  • 问题:if a会将NoneFalse0""[]等均判定为假,但实际业务中可能需要区分这些情况(如“None代表未初始化,[]代表已初始化但为空”);
  • 解决方案:根据业务逻辑做明确判断,而非依赖if a的模糊判定:
    # 坏示例:无法区分None和空列表
    if not a:print("错误")# 好示例:明确区分None和空列表
    if a is None:print("未初始化")
    elif len(a) == 0:print("已初始化但为空")
    

4.2. 压缩变量的类型范围

  • 尽量确保变量的类型可预测(如明确a是“列表”或“布尔值”),减少“跨类型真值判定”的风险;
  • 示例:若a的取值仅为None或列表,可先判断a is not None,再判断列表是否非空,逻辑更清晰。

4.3. 避免滥用a == Truea is True

  • 仅当需精确判断“是否为True对象”时,用a is True
  • 永远不要用a == True(冗余且有重载风险);
  • 若需判断“真值”,直接用if a(简洁且符合Python习惯)。
http://www.dtcms.com/a/450585.html

相关文章:

  • AI智能体升级实战:从规则匹配到Function Call,准确率提升86%的技术选型之路
  • 威联通nas 做网站湖州市南浔区建设局网站
  • C47-数组指针
  • 品牌网站建设咨询新产品上市推广策划方案
  • 男和男做的视频网站网站被攻击如何处理
  • 石家庄seo关键词网站推广优化怎样
  • 卓越建站快车南充建设企业网站
  • MySQL删除数据后表空间处理
  • 在线学习建设网站宁波易通建设网站
  • 济南网站制作企业设计网站的步骤有哪些
  • LeetCode:96.只出现一次的数字
  • 我国空间站建造西安做网站推广
  • 算法竞赛补题1
  • 网站优化设计公司百度小程序平台
  • 衡水网站制作费用潜山做网站
  • 光全息|OAM-旋转双维度复用全息
  • 发布网站iis上报404错误网站建设的行业分析
  • 专业购物网站建设网站备案 互联网信息
  • 光通信|OAM-偏振并行(解)复用器
  • 企业级大模型部署
  • FreeRTOS与信号量(四)
  • 欧洲网站服务器织梦网站更改网站的导航
  • 怎么搭建mysql数据库网站网站做多语言
  • 网站开发带后台南通网站建设心得
  • 福田做棋牌网站建设多少钱如何开发微信小程序商店
  • 运营网站是多少沧州开发网站多少钱
  • 泰州模板建站哪家好海外网站有哪些
  • 自主建设网站的意义软件园做网站
  • Linux内核进程管理子系统有什么第六十三回 —— 进程主结构详解(59)
  • 辽宁平台网站建设平台做网站引流做什么类型的网站最好