Python温度转换类Temperature中描述符的运行原理疑问
Python描述符执行流程答疑
核心疑问解答
- 你对触发逻辑的判断是正确的:执行
t1.kelvin=50时,确实会调用Kelvin类的__set__方法。 - 你输入的50不会直接存储,这套实现的设计是所有温标统一以摄氏度为基准存储,最终值存在
Celsius描述符实例的val属性中。
逐行执行流程拆解
第一步:实例化Temperature类得到t1
Temperature类的三个类属性celsius、fahrenheit、kelvin都是提前创建好的描述符实例,且都属于实现了__get__、__set__的数据描述符,优先级高于实例自身的属性,操作t1的这三个属性时都会优先触发对应描述符的方法。
第二步:执行t1.kelvin=50赋值
- Python检测到要给实例
t1的kelvin属性赋值,首先查找Temperature类的属性,发现kelvin是数据描述符,直接调用它的__set__方法,传入三个隐含参数:- 描述符自身的实例(即
Kelvin类的实例) instance:当前操作的t1实例value:你输入的赋值50
- 描述符自身的实例(即
- 进入
Kelvin的__set__方法,执行转换逻辑:instance.celsius = (50 - 273.15),计算得到摄氏度值为-223.15,接下来要给t1的celsius属性赋值。 - 赋值
instance.celsius = -223.15时,同样触发Celsius描述符的__set__方法,把-223.15存入Celsius描述符实例的val属性中,赋值完成。
后续读取逻辑验证
你赋值完成后读取任意温标的属性,都是基于存储的摄氏度值实时计算的:
- 读取
t1.celsius:触发Celsius的__get__方法,直接返回存储的val值-223.15 - 读取
t1.kelvin:触发Kelvin的__get__方法,用t1.celsius + 273.15计算得到50,和你赋值的结果一致 - 读取
t1.fahrenheit:触发Fahrenheit的__get__方法,用t1.celsius * 1.8 +32计算得到对应华氏度值
你可能遗漏的基础概念
数据描述符的优先级规则:如果类属性是实现了__set__和__get__的数据描述符,那么当你对实例的同名属性进行读、写操作时,Python会完全忽略实例自身的__dict__存储,强制调用描述符的对应方法,这就是为什么你操作kelvin、fahrenheit属性时,最终都会落到对celsius描述符的读写上。
内容的提问来源于stack exchange,提问作者TommyP
相关产品推荐
相关产品推荐

