简体   繁体   中英

abstractmethod decorator to all methods in class

I tried to make my realization where i don't need to use all times to all methods decorator @abstractmethod

Firstly, i realize class decorator, but this don't need any result:

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()

Secondly, i tried make it in __init__ method in class and it's don't give any result too:

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()

How can i realize a way where all methods in class decorated with @abstractmethod ?

Like @juanpa.arrivillaga mentions, it's too late to decorate an abstract class after the class is instantiated since ABC alters its class members with its metaclass, ABCMeta .

Instead, you can subclass ABCMeta (as Interface in the example below) and perform modifications to the classdict parameter of the class constructor before calling the constructor of the superclass.

Since child classes are supposed to implement abstract methods by default and not continue to declare methods abstract in typical cases, you should avoid decorating methods of child classes with abstractmethod , but since child classes would inherit the metaclass of the parent, you would have to explicitly make the constructor of the Interface return an object of ABCMeta instead of Interface itself so that the custom behavior would not be inherited:

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)

so that:

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

    def bar(self):
        pass

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

b = B()

would produce:

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

while:

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

    def bar(self):
        pass

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

    def bar(self):
        pass

would run with no error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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