从docs
从ABCMeta衍生元类不能被实例化,除非所有的 它的抽象方法和属性被覆盖。
我改变了你创建的基类class Mine(metaclass=ABCMeta):
和收到的错误
Traceback (most recent call last):
File "g.py", line 24, in <module>
Child().settings
TypeError: Can't instantiate abstract class Child with abstract methods settings
这样就使得问题更加明确。要解决该问题,只需让子类创建属于自己的settings
属性。现在他们被绑定到具体方法而不是抽象方法。
from abc import ABCMeta,abstractmethod
class Mine(object):
__metaclass__ = ABCMeta
@abstractmethod
def _get_stuff(self):
raise NotImplementedError()
@abstractmethod
def _set_stuff(self, value):
raise NotImplementedError()
settings = property(_get_stuff, _set_stuff)
def do_stuff_with_settings(self):
return settings
class Child(Mine):
def _get_stuff(self):
return 1
def _set_stuff(self):
pass
settings = property(_get_stuff, _set_stuff)
Child().settings
UPDATE
这不只是一个ABC的问题。你有覆盖属性方法的任何子类都有这个问题。在这里,我试图重写一个getter,但发现我仍然得到了父母的看法:
>>> class Foo:
... def __init__(self, val):
... self._val = val
... def _get_val(self):
... return self._val
... def _set_val(self, val):
... self._val = val
... val = property(_get_val, _set_val)
...
>>> class Bar(Foo):
... def _get_val(self):
... return self._val + 2
...
>>> print('want 3, got', Bar(1).val)
want 3, got 1
更新2
的问题是,property
结合它被定义在类方法。如果你不介意实现中间函数,那么你可以让他们在运行时解析目标方法,在孩子重写它们之后。在这里,_get_stuff
在运行时调用_get_stuff_impl
,您将获得子版本。
from abc import ABCMeta,abstractmethod
class Mine(metaclass=ABCMeta):
def _get_stuff(self):
return self._get_stuff_impl()
@abstractmethod
def _get_stuff_impl(self):
raise NotImplementedError()
def _set_stuff(self, value):
return self._set_stuff_impl(value)
@abstractmethod
def _set_stuff_impl(self, value):
raise NotImplementedError()
settings = property(_get_stuff, _set_stuff)
def do_stuff_with_settings(self):
return settings
class Child(Mine):
def _get_stuff_impl(self):
return 1
def _set_stuff_impl(self):
pass
# settings = property(_get_stuff, _set_stuff)
Child().settings
你想通过这种方式来解决你的问题? –
有许多功能是通用的(对于每个孩子都是相同的),它们使用该设置。我不希望这些函数引用父类中不存在的变量(尽管python不会抱怨)。 –
可能'do_stuff_with_settings''返回属性(self._get_stuff,self._set_stuff)' –