鱼C论坛

 找回密码
 立即注册
查看: 1060|回复: 2

[已解决]求助,关于__get()__和__set__调用问题

[复制链接]
发表于 2020-3-19 23:18:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在零基础入门学py中 P12_8的温度转换的例子:
class Celsius:
    def __init__(self,value=26.0):
        self.value = float(value)

    def __get__(self,instance,owner):
        return self.value

    def __set__(self,instance,value):
        self.value = float(value)

class Fahrenheit:
    def __get__(self,instance,owner):
        return instance.cel * 1.8 + 32

    def __set__(self,instance,value):
        instance.cel = (float(value)- 32) / 1.8
                        
class Temperature:
    cel = Celsius()
                        
    fah = Fahrenheit()
摄氏度转华氏度的例子,输出结果为
>>> temp = Temperature()
>>> temp.cel = 30
>>> temp.fah
86.0
我输入温度temp.cel = 30.0也就是先执行Celsiues __set__部分 接着执行Fahrenheit 里__set__部分才对,为什么会执行__get__的内容,这个30.0是在属性分配操作中调用,并没有访问,为什么会执行__get__的内容?
请大神解答
最佳答案
2020-3-20 14:07:49
我不知道你对__get__()和__set__()有多少理解。python中如果一个类实现了__get__、__set__、__delete__三个方法的任意一个方法就是描述器。也就是说class Celsius和class Fahrenheit都是描述器。
Temperature类中有两个属性分别是以上两个类的实例,所以在Temperature类的实例temp中一旦触发描述器方法就会去调用对应描述器内的对应函数。
我在你的程序的基础上添加了一些print语句,可以很好的观察如何调用描述器方法的。
#!/usr/bin/python3
class Celsius:
    def __init__(self,value=26.0):
        self.value = float(value)

    def __get__(self,instance,owner):
        print('In Celsius.__get__()....',instance,owner.__name__)
        return self.value

    def __set__(self,instance,value):
        print('In Celsius.__set__()....',instance,value)
        self.value = float(value)

class Fahrenheit:
    def __get__(self,instance,owner):
        print('In Fahrenheit.__get__()....',instance,owner.__name__)
        return instance.cel * 1.8 + 32   #因为instance是一个Temperature类的实例temp,这里会调用数据描述器Celsius的__get__方法

    def __set__(self,instance,value):
        print('In Fahrenheit.__set__()....',instance,value)
        instance.cel = (float(value)- 32) / 1.8
                        
class Temperature:
    cel = Celsius()#Temperature类属性放一个对象Celsius的实例赋值给cel
    print(cel)
    fah = Fahrenheit()#Temperature类属性放一个对象Fahrenheit的实例赋值给fah
    print(fah)

print('frist sentence')
temp = Temperature()
print('second sentence')
temp.cel = 50# 修改描述器同名属性值,会调用数据描述器Celsius的__set__方法
print('thrid sentence')
print(temp.fah)# 实例调用类的属性描述器,调用数据描述器Fahrenheit的__get__方法
print('forth sentence')
print(temp.cel)# 实例调用类的属性描述器,调用数据描述器Celsius的__get__方法

运行结果:
<__main__.Celsius object at 0x7f7f0ac2d0b8>
<__main__.Fahrenheit object at 0x7f7f0ac2d0f0>
frist sentence
second sentence
In Celsius.__set__().... <__main__.Temperature object at 0x7f7f0ac2d128> 50
thrid sentence
In Fahrenheit.__get__().... <__main__.Temperature object at 0x7f7f0ac2d128> Temperature
In Celsius.__get__().... <__main__.Temperature object at 0x7f7f0ac2d128> Temperature
122.0
forth sentence
In Celsius.__get__().... <__main__.Temperature object at 0x7f7f0ac2d128> Temperature
50.0
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-3-20 14:07:49 | 显示全部楼层    本楼为最佳答案   
我不知道你对__get__()和__set__()有多少理解。python中如果一个类实现了__get__、__set__、__delete__三个方法的任意一个方法就是描述器。也就是说class Celsius和class Fahrenheit都是描述器。
Temperature类中有两个属性分别是以上两个类的实例,所以在Temperature类的实例temp中一旦触发描述器方法就会去调用对应描述器内的对应函数。
我在你的程序的基础上添加了一些print语句,可以很好的观察如何调用描述器方法的。
#!/usr/bin/python3
class Celsius:
    def __init__(self,value=26.0):
        self.value = float(value)

    def __get__(self,instance,owner):
        print('In Celsius.__get__()....',instance,owner.__name__)
        return self.value

    def __set__(self,instance,value):
        print('In Celsius.__set__()....',instance,value)
        self.value = float(value)

class Fahrenheit:
    def __get__(self,instance,owner):
        print('In Fahrenheit.__get__()....',instance,owner.__name__)
        return instance.cel * 1.8 + 32   #因为instance是一个Temperature类的实例temp,这里会调用数据描述器Celsius的__get__方法

    def __set__(self,instance,value):
        print('In Fahrenheit.__set__()....',instance,value)
        instance.cel = (float(value)- 32) / 1.8
                        
class Temperature:
    cel = Celsius()#Temperature类属性放一个对象Celsius的实例赋值给cel
    print(cel)
    fah = Fahrenheit()#Temperature类属性放一个对象Fahrenheit的实例赋值给fah
    print(fah)

print('frist sentence')
temp = Temperature()
print('second sentence')
temp.cel = 50# 修改描述器同名属性值,会调用数据描述器Celsius的__set__方法
print('thrid sentence')
print(temp.fah)# 实例调用类的属性描述器,调用数据描述器Fahrenheit的__get__方法
print('forth sentence')
print(temp.cel)# 实例调用类的属性描述器,调用数据描述器Celsius的__get__方法

运行结果:
<__main__.Celsius object at 0x7f7f0ac2d0b8>
<__main__.Fahrenheit object at 0x7f7f0ac2d0f0>
frist sentence
second sentence
In Celsius.__set__().... <__main__.Temperature object at 0x7f7f0ac2d128> 50
thrid sentence
In Fahrenheit.__get__().... <__main__.Temperature object at 0x7f7f0ac2d128> Temperature
In Celsius.__get__().... <__main__.Temperature object at 0x7f7f0ac2d128> Temperature
122.0
forth sentence
In Celsius.__get__().... <__main__.Temperature object at 0x7f7f0ac2d128> Temperature
50.0
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-20 20:48:25 | 显示全部楼层
sunrise085 发表于 2020-3-20 14:07
我不知道你对__get__()和__set__()有多少理解。python中如果一个类实现了__get__、__set__、__delete__三 ...

理解了,还是对get和set用法之前没搞懂,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-25 04:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表