繁体   English   中英

类中所有方法的抽象方法装饰器

[英]abstractmethod decorator to all methods in class

我试图让我意识到我不需要一直使用所有方法装饰器@abstractmethod

首先,我实现了类装饰器,但这不需要任何结果:

from abc import ABC, abstractmethod


def interface(cls):
   for attr in cls.__dict__:
      if callable(getattr(cls, attr)):
         setattr(cls, attr, abstractmethod(getattr(cls, attr)))
    
   return cls


@interface
class A(ABC):
   def foo(self):
      pass

   def bar(self):
      pass


class B(A):
   def foo(self):
      pass

b = B()

其次,我尝试在类中的__init__方法中创建它,但它也没有给出任何结果:

class Interface(ABC):
    def __init__(self):
        for attr in self.__dict__:
            attr_obj = getattr(self, attr)

            if callable(attr_obj):
                setattr(self, attr, abstractmethod(attr_obj))

class A(Interface):
   def __init__(self):
      super().__init__()

   def foo(self):
      pass

   def bar(self):
      pass


class B(A):
   def foo(self):
      pass


b = B()

我怎样才能实现类中所有方法都用@abstractmethod装饰的方法?

就像@juanpa.arrivillaga 提到的那样,在类被实例化后装饰抽象类为时已晚,因为ABC用它的元类ABCMeta改变了它的类成员。

相反,您可以子类化ABCMeta (作为下面示例中的Interface )并调用超类的构造函数之前修改类构造函数的classdict参数。

由于子类应该默认实现抽象方法,并且在典型情况下不会继续声明抽象方法,因此您应该避免使用abstractmethod装饰子类的方法,但是由于子类会继承父类的元类,因此您必须明确地使Interface的构造函数返回ABCMeta的对象而不是Interface本身,以便不会继承自定义行为:

from abc import ABCMeta, abstractmethod

class Interface(ABCMeta):
    def __new__(metacls, name, bases, classdict):
        for attr, value in classdict.items():
            if callable(value):
                classdict[attr] = abstractmethod(value)
        return super().__new__(ABCMeta, name, bases, classdict)

以便:

class A(metaclass=Interface):
    def foo(self):
        pass

    def bar(self):
        pass

class B(A):
    def foo(self):
        pass

b = B()

会产生:

TypeError: Can't instantiate abstract class B with abstract method bar

尽管:

class A(metaclass=Interface):
    def foo(self):
        pass

    def bar(self):
        pass

class B(A):
    def foo(self):
        pass

    def bar(self):
        pass

会运行没有错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM