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

时间:2014-03-09 09:55:02

标签: python properties

我已经尝试了一段时间来了解@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没有按我假设的顺序执行?

2 个答案:

答案 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在实例上查找属性时,会发生以下搜索:

  1. 在类(和基础)上查找数据描述符
  2. 在实例
  3. 上查找属性
  4. 在类(和基础)上查找属性,包括非数据描述符。
  5. 当您尝试访问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,因为你没有定义删除器。