Python@property与它返回的字段id相同

Python@property与它返回的字段id相同,python,properties,Python,Properties,为了更好地理解属性,我制作了以下简单片段: 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")

为了更好地理解属性,我制作了以下简单片段:

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
当我返回指向函数的指针(不确定指针在这个上下文中是否正确?)时,没有任何条件,这是非常明显的。但是在这里,我的第一个代码片段是如何工作的,即使
self.\u val
self.val
是同一个对象

为什么f1._val和f1.val都是同一个对象

因为您正在将它们设置为代码中的同一对象。您获取您的值,在本例中为
2
,并将其分配给
self.val
self.\u val

你所做的相当于

a=2

b=2

a==b

True

另外,当类型(f1.val)是函数时,为什么它是int


使用
@属性
装饰器时,该方法不再可调用。您可以将其视为一个属性。

在您的示例中,
val
是一个描述符,如中所述。使用描述符,对变量的访问被替换为对其
\uuuuu get\uuuuu
\uuuuu set\uuuuuu
\uuu delete\uuuu
方法的调用。
属性
函数是创建描述符的快捷方式。由于“property”和“descriptor”的含义相同,我不知道为什么会使用两个不同的名称

val
绑定到一个对象,该对象的
\uuu get\uu
执行函数体。它获取局部变量
\u val

@val.setter
def val(自身,值):
如果值<0:
提升值错误(“值必须大于0”)
其他:
自我价值=价值
绑定到
val
的对象将被更新,以便其
\uuuuuu设置\uuuuu
执行函数体,设置
\u val

当python执行
f1.val
时,它会获取由“val”引用的对象,但在返回之前,它会检查该对象是否具有
\uuuu get\uuu
。如果是这样,它将调用
\uuu get\uu
并使用其返回值,而不是返回对象。在您的情况下,“\u val”返回,因此它们自然是相等的


如果将属性函数更改为获取“val”而不是“_val”,python仍然遵循相同的规则。“val”是一个描述符,因此会调用它的
\uuuu get\uuuu
,它会再次尝试获取“val”,但它是一个描述符。。。“为什么
f1.\u val
f1.val
都是同一个对象?”因为
val
属性getter只返回
self.\u val
。。。我不确定你不明白的是什么。当您执行
f1.val
时,它调用getter并计算为该值,您理解它吗?
foo.val
不再是一个函数。它是一个
属性
<代码>属性对象实现。基本上,一些类上的描述符,
MyClass。一些描述符可以定义一个
\uuuu get\uuuu
\uu set\uuuu
\uu delete\uuu
方法。创建实例时,
myinstance=MyClass()
然后将为
myinstance.my_描述符
myinstance.my_descriptor=foo
,调用描述符
\uu get\uuuuuuuuuuuu
myinstance.my_descriptor=foo
,调用
myinstance>myinstance.my_descriptor=foo
,和
del myinstance.my_描述符
分别是当类中定义了另一个方法时,例如
func
返回
int
,我将以非常相同的方式实例化类
type(f1.func)
是方法,而
type(f1.func())
是int。这对我来说很有意义。那么
type(f1.val())
也应该是一个int,而
type(f1.val)
应该是我所理解的一个方法(不过我可能错了)*它不是一个方法,而是一个
属性
对象。你知道
@property
在做什么吗?你知道什么是装饰师吗?我在上面解释了描述符,
property
也是一个decorator,但这主要是语法上的suguar。基本上,
@property def val(self):…
等同于
def val(self):…
然后
val=property(val)
。因此类上的
val
属性不再是函数/方法。它是一个
属性
描述符。注意,函数也是描述符,这就是它们“神奇地”提供实例作为第一个参数的方式是的,是的,谢谢。我的评论是在网页刷新之前发布的,我看到了你的第二条评论。
RecursionError: maximum recursion depth exceeded in comparison
@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