我有以下代码段:
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'
行。
任何人都知道为什么会这样吗?
答案 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