我已经尝试了一段时间来了解@property在python中是如何工作的。我通过阅读本网站上的类似问题寻找答案,但它仍然是与主题相关的东西,我无法指出它是如何工作的。例如以下情况:
class MyClass(object):
def __init__(self):
self.name = 'x'
del self.name
@property
def name(self):
return 'y'
my_class = MyClass()
print my_class.name # AttributeError: can't set attribute (self.name = 'x')
为什么这不起作用?据我所知,你不能设置一个与现有属性同名的属性,这就是为什么你应该在_
前加self._name
所以{{1}}为我的情况,但我已经删除了self.name为什么它仍然很重要?或者python没有按我假设的顺序执行?
答案 0 :(得分:3)
self.name
中对__init__
的任何访问都会与您的媒体进行互动。你没有绕过这里的房产。
您的媒体资源未定义设定者或删除者,因此不允许分配到self.name
或删除del self.name
。
如果添加了setter或者删除器,__init__
中的代码将起作用:
class MyClass(object):
def __init__(self):
self.name = 'x'
del self.name
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
@name.deleter
def name(self):
del self._name
我更改了属性以使用名为_name
的不同实例属性来干扰属性本身。 self._name
不是属性,因此您可以直接设置和删除它。
完整的技术说明是property
对象是descriptor object,具体是classmethod
。它是数据描述符,这意味着它始终在任何实例属性之前使用。
常规非数据描述符(如函数,staticmethod
和__get__
对象)只有__set__
方法。数据描述符还至少定义了__delete__
或self.name
方法。当Python在实例上查找属性时,会发生以下搜索:
当您尝试访问self
时,您正在寻找name
上的属性。 Python在类上找到MyClass.name.__get__(self, MyClass)
属性,这是一个数据描述符。因此,此处使用第一步,name
用于(间接)调用您的self.name
函数。
尝试分配到MyClass.name.__set__(self, newvalue)
时,会调用del self.name
,而对于MyClass.name.__delete__(self)
,会调用property
。如果您未在类中定义setter或deleter函数,则AttributeError
对象的默认操作是引发{{1}}。
答案 1 :(得分:1)
该属性在__init__
之后不存在 - 它在调用__init__
之前就已存在。当你尝试做
self.name = 'x'
您拨打name
媒体资源__set__
,AttributeError
,因为您从未定义过设置者。
致电时
del self.name
您(将)调用name
属性的__delete__
(如果您到达了该行)。这也是AttributeError
,因为你没有定义删除器。