无法设置与已删除属性同名的属性



我已经尝试了一段时间来理解@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,但我已经删除了self。name为什么它仍然重要?还是python没有按照我假设的顺序执行?

任何访问__init__中的self.name都会与您的属性交互。你没有绕过这个属性。

你的属性没有定义setter或deleter,所以不允许给self.name赋值或用del self.name删除。

如果您添加setter或deleter,则__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对象是一个描述符对象,并且是一个特定的描述符对象。它是一个数据描述符,这意味着它总是在任何实例属性之前使用。

常规的非数据描述符(如函数、classmethodstaticmethod对象)只有__get__方法。数据描述符还至少定义了__set____delete__方法。当Python在实例中查找属性时,会进行以下搜索:

  1. 查找类(和基类)上的数据描述符
  2. 查找实例
  3. 上的属性
  4. 查找类(和基)的属性,包括非数据描述符。

当您尝试访问self.name时,您正在寻找self上的属性。Python在类上查找name属性,这是一个数据描述符。因此这里使用了第一步,并且使用MyClass.name.__get__(self, MyClass)(间接)调用name函数。

当试图分配给self.name时,MyClass.name.__set__(self, newvalue)被调用,对于del self.name, MyClass.name.__delete__(self)被调用。如果您没有在类中定义setter或deleter函数,则property对象的默认操作是引发AttributeError

属性在__init__之后不存在-它在__init__被调用之前已经存在了。当你试图做

self.name = 'x'

你调用name属性的__set__, AttributeError,因为你从来没有定义setter。

当你呼叫

del self.name

你(将)调用name属性的__delete__(如果你到达了行)。这也是AttributeError,因为您没有定义deleter。

相关内容

  • 没有找到相关文章

最新更新