鱼C论坛

 找回密码
 立即注册
查看: 1708|回复: 3

[已解决]__set__的小问题

[复制链接]
发表于 2023-8-10 15:35:27 | 显示全部楼层 |阅读模式

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

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

x
class MyDes:
    def __init__(self, initval=None, name=None):
        self.val = initval
        self.name = name

    def __get__(self, instance, owner):
        print("正在获取变量:", self.name)
        return self.val

    def __set__(self, instance, value):
        print("正在修改变量:", self.name)
        super().__setattr__(self.name,value)
        

    def __delete__(self, instance):
        print("正在删除变量:", self.name)
        print("噢~这个变量没法删除~")


class Test:
    x = MyDes(10, 'x')


class MyDes:
    def __init__(self, initval=None, name=None):
        self.val = initval
        self.name = name

    def __get__(self, instance, owner):
        print("正在获取变量:", self.name)
        return self.val

    def __set__(self, instance, value):
        print("正在修改变量:", self.name)
        self.val =  value
        

    def __delete__(self, instance):
        print("正在删除变量:", self.name)
        print("噢~这个变量没法删除~")


class Test:
    x = MyDes(10, 'x')



为什么两种代码相差这么大,能帮解释一下吗
为什么第二种代码不会有无限递归错误,self.val = value 不会再触发__set__(self,instance,value)吗
在帮忙解释一下__set__ 和__setattr__的区别
再解释一下
最佳答案
2023-8-10 15:35:45
这两种代码相差很大,因为第一种代码中的__set__方法调用了super().__setattr__(self.name, value)来修改属性值,而super()会调用父类的__setattr__方法,从而避免了无限递归错误。

在第二种代码中,__set__方法直接使用self.val = value来修改属性值,这不会触发__set__方法的递归调用。这是因为__set__方法中的self.val = value是对实例属性进行赋值操作,而不是调用__set__方法来修改属性值。

__set____setattr__的区别在于:

· __set__是描述符协议中定义的特殊方法,用于控制属性赋值时的行为。它只能定义在描述符类中,并且可以通过属性访问方式来调用,例如instance.attr = value
· __setattr__是对象的特殊方法,用于给对象的属性赋值时的行为。它可以定义在普通类或描述符类中,并且可以通过属性赋值方式来调用,例如instance.attr = value

总结起来,__set__是描述符类中用于控制属性设置过程的方法,而__setattr__是对象中用于控制属性设置过程的方法。
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-8-10 15:35:44 | 显示全部楼层
第一种代码中,在__set__方法中使用了super().__setattr__(self.name,value)来设置属性的值。这会触发父类的__setattr__方法,而父类的__setattr__方法又会调用__set__方法,从而导致无限递归错误。

第二种代码中,直接将属性的值赋给self.val,而没有调用父类的__setattr__方法。因此,不会再次触发__set__方法,也就避免了无限递归错误。

__set__和__setattr__的区别在于:
· __set__是描述符(descriptor)协议中的方法,用于在访问属性时进行拦截和处理。它只能在描述符类中定义,通过实例对象访问属性时才会被调用。
· __setattr__是对象的特殊方法,用于设置对象的属性值。它可以在任何类中定义,通过实例对象设置属性值时会被调用。

总结起来,__set__是描述符类中用于拦截属性设置的方法,而__setattr__是对象的特殊方法,用于设置属性值。两者的调用时机和使用场景不同。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-10 15:35:45 | 显示全部楼层    本楼为最佳答案   
这两种代码相差很大,因为第一种代码中的__set__方法调用了super().__setattr__(self.name, value)来修改属性值,而super()会调用父类的__setattr__方法,从而避免了无限递归错误。

在第二种代码中,__set__方法直接使用self.val = value来修改属性值,这不会触发__set__方法的递归调用。这是因为__set__方法中的self.val = value是对实例属性进行赋值操作,而不是调用__set__方法来修改属性值。

__set____setattr__的区别在于:

· __set__是描述符协议中定义的特殊方法,用于控制属性赋值时的行为。它只能定义在描述符类中,并且可以通过属性访问方式来调用,例如instance.attr = value
· __setattr__是对象的特殊方法,用于给对象的属性赋值时的行为。它可以定义在普通类或描述符类中,并且可以通过属性赋值方式来调用,例如instance.attr = value

总结起来,__set__是描述符类中用于控制属性设置过程的方法,而__setattr__是对象中用于控制属性设置过程的方法。
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-10 15:35:45 | 显示全部楼层
第一种代码中,在__set__方法内部使用了super().__setattr__(self.name, value)来设置属性值。这里使用了super()函数调用父类的__setattr__方法,而不是直接通过self.val = value赋值操作。

对于第二种代码,__set__方法直接使用self.val = value来设置属性值,没有调用父类的__setattr__方法。因此,不会发生无限递归错误。

区别解释如下:

- __set__方法:定义了当尝试给descriptor所在的属性赋值时的行为。在设置属性值时,__set__方法会被调用。
- __setattr__方法:定义了当尝试给对象的属性赋值时的行为。它适用于所有属性,而不仅仅是descriptor。

两者的区别在于调用场景和功能:

- __set__方法是在descriptor被设置为另一个类的属性时被调用,可以对属性赋值进行特定的处理和限制。
- __setattr__方法是在对象的属性被赋值时被调用,无论该属性是否是descriptor,它都会被触发。可以用于实现一般的属性赋值逻辑,但需要注意避免无限递归的情况。

以下是修改后的代码示例:
class MyDes:    def __init__(self, initval=None, name=None):        self.val = initval        self.name = name    def __get__(self, instance, owner):        print("正在获取变量:", self.name)        return self.val    def __set__(self, instance, value):        print("正在修改变量:", self.name)        self.val = value    def __delete__(self, instance):        print("正在删除变量:", self.name)        print("噢~这个变量没法删除~")class Test:    x = MyDes(10, 'x')
请记住,在代码示例中进行了适当的格式化和缩进。

如果回答对你有帮助,请给我一个最佳答案!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-25 10:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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