簡體   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