首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >了解python中的元类

了解python中的元类
EN

Stack Overflow用户
提问于 2018-07-18 15:18:41
回答 1查看 90关注 0票数 0

我有像下面这样的BaseDerived

代码语言:javascript
复制
class Base():
    def foo(self):
        return self.bar() 

class Derived(Base):
    def foo2(self):
        return "i am foo2"

现在,当我想要确保无论谁扩展Base类,都必须实现bar()方法,所以我创建了元类来挂钩派生类的构造,所以现在Base类看起来像是跟随着BaseMeta元类。

代码语言:javascript
复制
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时,它返回了BaseDerived类的2条记录,如follow。

代码语言:javascript
复制
 {'__module__': '__main__', '__qualname__': 'Base', 'foo': <function 
 Base.foo at 0x7ffbaae436a8>}
 {'__module__': '__main__', '__qualname__': 'Derived', 'bar': <function 
 Derived.bar at 0x7ffbaae437b8>}

我在__new__中的代码中断了,因为Base没有bar,但我只想签入派生类,所以我重写了我的metaclass,如下所示。

代码语言:javascript
复制
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

这是正确的方法吗?还是我们可以使用其他最好的方法?

EN

回答 1

Stack Overflow用户

发布于 2018-07-18 15:27:06

您可以使用stdlib中的abc模块,它提供了执行此操作的工具。https://docs.python.org/3/library/abc.html

代码语言:javascript
复制
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的内容之前,不会引发任何错误。例如:

代码语言:javascript
复制
class Base():
    def foo(self):
        return self.bar() 

    def bar(self):
        raise NotImplementedError
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51395847

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档