Python无法在abstractproperty上设置属性

时间:2016-03-11 22:02:12

标签: python

我有以下代码段:

from abc import abstractproperty

class Base(object):
  @abstractproperty
  def foo(self):
    print 'wat'

class C(Base):
  def __init__(self):
    self.foo = 'test'
    self.bar = 'test2'

c = C()

当我执行它时,它给出了栈跟踪:

in __init__ AttributeError: can't set attribute

self.foo = 'test'行。

任何人都知道为什么会这样吗?

2 个答案:

答案 0 :(得分:3)

首先,请注意您忘记使用ABCMeta作为您的元类。将您的代码更改为:

from abc import ABCMeta, abstractproperty

class Base(object):
  __metaclass__ = ABCMeta
  @abstractproperty
  def foo(self):
    print 'wat'

class C(Base):
  ...

c = C()

你会看到这个错误的错误:

Traceback (most recent call last):
  File "a.py", line 14, in <module>
    c = C()
TypeError: Can't instantiate abstract class C with abstract methods foo

它告诉你需要为你的抽象属性做一个具体的实现。

但这还不够:要让self.foo = 'test'正常工作,你需要为你的财产实施一个具体的设定者。

最后,您的代码应如下所示:

from abc import ABCMeta, abstractproperty

class Base(object):

    __metaclass__ = ABCMeta

    @abstractproperty
    def foo(self):
        print 'wat'

class C(Base):

    @property
    def foo(self):
        # do something

    @foo.setter
    def foo(self, value):
        # do something else

    def __init__(self):
        self.foo = 'test'
        self.bar = 'test2'

c = C()

请记住,您可以在具体的属性代码中使用super()来使用抽象属性中的代码。

答案 1 :(得分:1)

您的代码定义了只读abstractproperty。见docs on ABC。此外,您没有将ABCMeta设置为元类,这是必须的。此外,abstractproperty抽象,这意味着必须在子类中被覆盖。

如果您想创建一个读写abstractproperty,请使用以下内容:

from abc import ABCMeta, abstractproperty

class Base(object):
    __metaclass__ = ABCMeta # This is required.

    def getfoo(self):
        pass # Getter for preprocessing when property 'foo' is requested
    def setfoo(self, thefoo):
        pass # Setter for preprocessing when property 'foo' is set
    foo = abstractproperty(getfoo, setfoo)

class C(Base):
    foo = '' # Overwrite abstract property

    def __init__(self):
        self.foo = 'test'
        self.bar = 'test2'

使用上面的代码,您可以实例化您的班级C并设置其属性foo

c = C()
print(c.foo)
>>> test