鱼C论坛

 找回密码
 立即注册
查看: 737|回复: 4

[已解决]第47课描述符有问题

[复制链接]
发表于 2020-4-4 00:17:22 | 显示全部楼层 |阅读模式

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

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

x
>>> class MyProperty:
        def __init__(self,fget=None,fset=None,fdel=None):
                self.fget = fget
                self.fset = fset
                self.fdel = fdel
        def __get__(self,instance,owner):
                return self.fget(instance)
        def __set__(self,instance,value):
                self.fset(instance,value)
        def __delete__(self,instance):
                self.fdel(instance)

               
>>> class C:
        def __init__(self):
                self._x = None
        def getX(self):
                return self._x
        def setX(self,value):
                self._x = value
        def delX(self):
                del self._x
        x = MyPropertys(getX, setX, delX)

>>> c.x = 'X-man'
>>> c.x
'X-man'
>>> c._x
'X-man'

问题:c.x='X-man'调用了MyProperty的__set__,__set__又调用了C的setX,setX只对c._x='X-man',并没有使c.x='X-man'。请问为什么c.x和c._x都为'X-man'?
最佳答案
2020-4-4 00:57:41
本帖最后由 sunrise085 于 2020-4-4 00:58 编辑

我不知道你对__get__()和__set__()有多少理解。python中如果一个类实现了__get__、__set__、__delete__三个方法的任意一个方法就是描述器。
帮你在函数中添加了一些print,可以看清楚函数在什么时候调用的
然后对关键的一些地方做了注释
class MyProperty:
        def __init__(self,fget=None,fset=None,fdel=None):
                self.fget = fget
                self.fset = fset
                self.fdel = fdel
        def __get__(self,instance,owner):
                print("MyProperty.__get__")
                return self.fget(instance)
        def __set__(self,instance,value):
                print("MyProperty.__set__")
                self.fset(instance,value)
        def __delete__(self,instance):
                print("MyProperty.__delete__")
                self.fdel(instance)
class C:
        def __init__(self):
                print("C.__init__")
                self._x = None
        def getX(self):
                print("C.getX")
                return self._x
        def setX(self,value):
                self._x = value
                print("C.setX")
        def delX(self):
                print("C.delX")
                del self._x
        x = MyProperty(getX, setX, delX)#C类属性放一个对象MyProperty的实例赋值给x
print("创建C类对象c")
c=C()
print("修改描述器同名属性值")
c.x='X_Man'     # 修改描述器同名属性值,会调用数据描述器MyProperty的__set__方法
print("访问描述器同名属性值")
print(c.x)     # 访问描述器同名属性值,会调用数据描述器MyProperty的__get__方法
print("下面这句不会触发描述器")
print(c._x)
运行结果
创建C类对象c
C.__init__
修改描述器同名属性值
MyProperty.__set__
C.setX
访问描述器同名属性值
MyProperty.__get__
C.getX
X_Man
下面这句不会触发描述器
X_Man

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-4-4 00:57:41 | 显示全部楼层    本楼为最佳答案   
本帖最后由 sunrise085 于 2020-4-4 00:58 编辑

我不知道你对__get__()和__set__()有多少理解。python中如果一个类实现了__get__、__set__、__delete__三个方法的任意一个方法就是描述器。
帮你在函数中添加了一些print,可以看清楚函数在什么时候调用的
然后对关键的一些地方做了注释
class MyProperty:
        def __init__(self,fget=None,fset=None,fdel=None):
                self.fget = fget
                self.fset = fset
                self.fdel = fdel
        def __get__(self,instance,owner):
                print("MyProperty.__get__")
                return self.fget(instance)
        def __set__(self,instance,value):
                print("MyProperty.__set__")
                self.fset(instance,value)
        def __delete__(self,instance):
                print("MyProperty.__delete__")
                self.fdel(instance)
class C:
        def __init__(self):
                print("C.__init__")
                self._x = None
        def getX(self):
                print("C.getX")
                return self._x
        def setX(self,value):
                self._x = value
                print("C.setX")
        def delX(self):
                print("C.delX")
                del self._x
        x = MyProperty(getX, setX, delX)#C类属性放一个对象MyProperty的实例赋值给x
print("创建C类对象c")
c=C()
print("修改描述器同名属性值")
c.x='X_Man'     # 修改描述器同名属性值,会调用数据描述器MyProperty的__set__方法
print("访问描述器同名属性值")
print(c.x)     # 访问描述器同名属性值,会调用数据描述器MyProperty的__get__方法
print("下面这句不会触发描述器")
print(c._x)
运行结果
创建C类对象c
C.__init__
修改描述器同名属性值
MyProperty.__set__
C.setX
访问描述器同名属性值
MyProperty.__get__
C.getX
X_Man
下面这句不会触发描述器
X_Man
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-4 02:28:18 | 显示全部楼层
sunrise085 发表于 2020-4-4 00:57
我不知道你对__get__()和__set__()有多少理解。python中如果一个类实现了__get__、__set__、__delete__三 ...

我分析的步骤:c.x='X-man'→__set__(c.x,c,C)→setX(c,'X-man)→c._x='X-man'
我不懂的是c.x在哪一步骤被赋值的,从我分析的步骤中看只有c._x被赋值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-4 02:32:00 | 显示全部楼层
麻麦皮 发表于 2020-4-4 02:28
我分析的步骤:c.x='X-man'→__set__(c.x,c,C)→setX(c,'X-man)→c._x='X-man'
我不懂的是c.x在哪一步骤 ...

程序第32行,就是修改c.x的属性值啊,将'X-man'赋值给了c.x,然后才有了后面的一系列操作啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-4 02:45:55 | 显示全部楼层
sunrise085 发表于 2020-4-4 02:32
程序第32行,就是修改c.x的属性值啊,将'X-man'赋值给了c.x,然后才有了后面的一系列操作啊

懂了,我想太多了...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-22 13:02

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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