__set__的小问题
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__的区别
再解释一下
第一种代码中,在__set__方法中使用了super().__setattr__(self.name,value)来设置属性的值。这会触发父类的__setattr__方法,而父类的__setattr__方法又会调用__set__方法,从而导致无限递归错误。
第二种代码中,直接将属性的值赋给self.val,而没有调用父类的__setattr__方法。因此,不会再次触发__set__方法,也就避免了无限递归错误。
__set__和__setattr__的区别在于:
· __set__是描述符(descriptor)协议中的方法,用于在访问属性时进行拦截和处理。它只能在描述符类中定义,通过实例对象访问属性时才会被调用。
· __setattr__是对象的特殊方法,用于设置对象的属性值。它可以在任何类中定义,通过实例对象设置属性值时会被调用。
总结起来,__set__是描述符类中用于拦截属性设置的方法,而__setattr__是对象的特殊方法,用于设置属性值。两者的调用时机和使用场景不同。 这两种代码相差很大,因为第一种代码中的__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__是对象中用于控制属性设置过程的方法。
如果问题已经解决,请设置最佳答案 第一种代码中,在__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')
请记住,在代码示例中进行了适当的格式化和缩进。
如果回答对你有帮助,请给我一个最佳答案!{:10_254:}{:10_254:}{:10_254:}
页:
[1]