2016-12-01 71 views
2

我需要父级中的设置来包含来自子级的函数。 (此父母的每个孩子都将使用该设置,但功能的定义方式将会改变)从具有相同抽象函数的父级属性调用子函数

这可能吗?目前,它似乎读取从父类未定义功能(并因此休息)

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 {"a": 2} 
    def _set_stuff(self): 
     pass 
    def do_stuff(self): 
     self.a = do_stuff_with_settings.a 
+0

你想通过这种方式来解决你的问题? –

+0

有许多功能是通用的(对于每个孩子都是相同的),它们使用该设置。我不希望这些函数引用父类中不存在的变量(尽管python不会抱怨)。 –

+0

可能'do_stuff_with_settings''返回属性(self._get_stuff,self._set_stuff)' –

回答

2

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 
+0

所以唯一的解决办法是代码重复? –

+0

@ north.mister - 如果你想使用属性,那么是的,那是唯一的方法。父'设置=属性(_get_stuff,_set_stuff)'绑定到父方法。这也不是一个抽象的方法。你会遇到与覆盖属性实现函数的任何子类相同的问题。 – tdelaney

+0

@ north.mister - 你可以游戏系统,但是...我已经提供了一个示例更新。 – tdelaney

相关问题