Python @属性 与其返回的字段相同的id
Python @property same id as field returned by it
我制作了这个简单的片段以更好地理解属性:
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
函数(一个由 [=20= 修饰,第二个由 @val.setter
修饰)更改为 return self.val
而不是 return self._val
.尝试实例化对象时,我得到:
RecursionError: maximum recursion depth exceeded in comparison
很明显,我 return 指向函数的指针(不确定指针在这种情况下是否正确?)没有条件。但是在这里,即使 self._val
和 self.val
是同一个对象,我的第一个片段如何工作得很好?
How is it, that both f1._val and f1.val are the same object?
因为您在代码中将它们设置为同一个对象。你取你的值,在本例中为 2
并将其分配给 self.val
和 self._val
你所做的相当于
a = 2
b = 2
a == b
True
Also, why type(f1.val) is int when it is a function?
使用 @property
装饰器时,该方法不再可调用。你几乎可以把它想象成一个属性。
在您的示例中,val
是 3.3.2.2. Implementing Descriptors 中描述的描述符。使用描述符,对变量的访问被替换为对其 __get__
、__set__
和 __delete__
方法的调用。 property
函数是创建描述符的快捷方式。由于“属性”和“描述符”是同一个东西,我不知道为什么使用两个不同的名称。
有
@property
def val(self):
return self._val
val
绑定到一个对象,其 __get__
执行函数体。它获取局部变量 _val
.
有
@val.setter
def val(self, value):
if value < 0:
raise ValueError("Value has to be larger than 0")
else:
self._val = value
绑定到 val
的对象已更新,以便其 __set__
执行函数体,设置 _val
.
当python执行f1.val
时,它得到“val”引用的对象,但在returning之前,它检查对象是否有__get__
.如果是这样,它不会 returning 对象,而是调用 __get__
并使用它的 return。在你的例子中,“_val”是 returned,所以它们自然是相等的。
如果您更改 属性 函数以获取“val”而不是“_val”,python 仍遵循相同的规则。 “val”是一个描述符,因此它的 __get__
被调用,它试图再次获取“val”,但它是一个描述符......等等。
我制作了这个简单的片段以更好地理解属性:
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
函数(一个由 [=20= 修饰,第二个由 @val.setter
修饰)更改为 return self.val
而不是 return self._val
.尝试实例化对象时,我得到:
RecursionError: maximum recursion depth exceeded in comparison
很明显,我 return 指向函数的指针(不确定指针在这种情况下是否正确?)没有条件。但是在这里,即使 self._val
和 self.val
是同一个对象,我的第一个片段如何工作得很好?
How is it, that both f1._val and f1.val are the same object?
因为您在代码中将它们设置为同一个对象。你取你的值,在本例中为 2
并将其分配给 self.val
和 self._val
你所做的相当于
a = 2
b = 2
a == b
True
Also, why type(f1.val) is int when it is a function?
使用 @property
装饰器时,该方法不再可调用。你几乎可以把它想象成一个属性。
在您的示例中,val
是 3.3.2.2. Implementing Descriptors 中描述的描述符。使用描述符,对变量的访问被替换为对其 __get__
、__set__
和 __delete__
方法的调用。 property
函数是创建描述符的快捷方式。由于“属性”和“描述符”是同一个东西,我不知道为什么使用两个不同的名称。
有
@property
def val(self):
return self._val
val
绑定到一个对象,其 __get__
执行函数体。它获取局部变量 _val
.
有
@val.setter
def val(self, value):
if value < 0:
raise ValueError("Value has to be larger than 0")
else:
self._val = value
绑定到 val
的对象已更新,以便其 __set__
执行函数体,设置 _val
.
当python执行f1.val
时,它得到“val”引用的对象,但在returning之前,它检查对象是否有__get__
.如果是这样,它不会 returning 对象,而是调用 __get__
并使用它的 return。在你的例子中,“_val”是 returned,所以它们自然是相等的。
如果您更改 属性 函数以获取“val”而不是“_val”,python 仍遵循相同的规则。 “val”是一个描述符,因此它的 __get__
被调用,它试图再次获取“val”,但它是一个描述符......等等。