【发布时间】:2020-10-14 20:47:34
【问题描述】:
我做了这个简单的 sn-p 来更好地理解属性:
class foo:
def __init__(self, val):
self.val = val
@property
def val(self):
return self._val
@val.setter
def val(self, value):
if value < 0:
raise ValueError("Value has to be larger than 0")
else:
self._val = value
f1 = foo(2)
print(id(f1._val) == id(f1.val)) #print true
现在我理解的比我写那段代码之前要少。为什么f1._val 和f1.val 是同一个对象?是不是在后台做了什么魔术?另外,为什么type(f1.val) 是int 而它是function?
另一件事是我将两个val 函数(一个由@property 装饰,第二个由@val.setter 装饰)更改为return self.val 而不是return self._val。当试图实例化我得到的对象时:
RecursionError: maximum recursion depth exceeded in comparison
当我毫无条件地返回指向函数的指针(不确定指针在这种情况下是否正确?)时,什么是非常明显的。但是在这里,即使 self._val 和 self.val 都是同一个对象,我的第一个 sn-p 是如何工作的?
【问题讨论】:
-
"
f1._val和f1.val是同一个对象,这是怎么回事?"因为val属性getter 只是返回self._val... 我不确定你不明白什么。当您执行f1.val它调用 getter 并评估该值时,您了解吗? -
foo.val不再是函数。这是一个property。property对象实现descriptor protocol。基本上,某个类的描述符MyClass.some_desriptor可以定义__get__、__set__和__delete__方法。当您创建实例时,myinstance = MyClass()将分别为myinstance.my_descriptor、myinstance.my_desriptor = foo和del myinstance.my_descriptor调用描述符__get__、__set__和__delete__方法 -
当类中定义了另一个方法时,例如
func返回一个int,我会以同样的方式实例化类,type(f1.func)是方法,而type(f1.func())是 int。对于我,这说得通。那么type(f1.val())也应该是一个int,而type(f1.val)应该是我理解的一种方法(但是我可能错了) -
*它不是一个方法,它是一个
property对象。你明白@property在做什么吗?你知道什么是装饰器吗?我在上面解释了描述符,property也是一个装饰器,但这主要是句法糖。基本上@property def val(self): ...等价于def val(self): ...然后val = property(val)。所以类的val属性不再是函数/方法。这是一个property描述符。注意,函数也是描述符,这就是它们“神奇地”提供实例作为第一个参数的方式 -
是的,是的,谢谢。我的评论是在网页刷新之前发布的,我看到了你的第二条评论。
标签: python properties