我有像下面这样的Base
和Derived
类
class Base():
def foo(self):
return self.bar()
class Derived(Base):
def foo2(self):
return "i am foo2"
现在,当我想要确保无论谁扩展Base
类,都必须实现bar()
方法,所以我创建了元类来挂钩派生类的构造,所以现在Base
类看起来像是跟随着BaseMeta
元类。
class BaseMeta(type):
def __new__(cls, name, bases, body):
if not "bar" in body:
raise TypeError("bar not implemented")
return super().__new__(cls, name, bases, body)
class Base(metaclass=BaseMeta):
def foo(self):
return self.bar()
问题是,当我查看body时,它返回了Base
和Derived
类的2条记录,如follow。
{'__module__': '__main__', '__qualname__': 'Base', 'foo': <function
Base.foo at 0x7ffbaae436a8>}
{'__module__': '__main__', '__qualname__': 'Derived', 'bar': <function
Derived.bar at 0x7ffbaae437b8>}
我在__new__
中的代码中断了,因为Base
没有bar
,但我只想签入派生类,所以我重写了我的metaclass
,如下所示。
def __new__(cls, name, bases, body):
if name !="Base" and not "bar" in body:
raise TypeError("bar not implemented")
return super().__new__(cls, name, bases, body)
我在我的__new__
方法中检查name != Base
。
这是正确的方法吗?还是我们可以使用其他最好的方法?
发布于 2018-07-18 15:27:06
您可以使用stdlib中的abc
模块,它提供了执行此操作的工具。https://docs.python.org/3/library/abc.html
import abc
class Base(abc.ABC):
@abc.abstractmethod
def bar(self):
pass
class Derived(Base):
pass
# This will raise an error because foo is not implemented
# >>> Derived()
# TypeError: Can't instantiate abstract class Derived with abstract methods bar
另一种策略是在引发NotImplementedError的基类上使用bar
方法。主要区别在于,在实际调用需要bar
的内容之前,不会引发任何错误。例如:
class Base():
def foo(self):
return self.bar()
def bar(self):
raise NotImplementedError
https://stackoverflow.com/questions/51395847
复制相似问题