抽象属性(不是属性)?

发布于 2021-01-29 18:44:54

定义抽象实例属性而不是属性的最佳实践是什么?

我想写一些像:

class AbstractFoo(metaclass=ABCMeta):

    @property
    @abstractmethod
    def bar(self):
        pass

class Foo(AbstractFoo):

    def __init__(self):
        self.bar = 3

代替:

class Foo(AbstractFoo):

    def __init__(self):
        self._bar = 3

    @property
    def bar(self):
        return self._bar

    @bar.setter
    def setbar(self, bar):
        self._bar = bar

    @bar.deleter
    def delbar(self):
        del self._bar

属性很方便,但是对于不需要计算的简单属性来说,这太过分了。这对于将由用户进行子类化和实现的抽象类尤为重要(我不想强迫某人@property只可以在中编写代码来使用self.foo = foo__init__)。

Python问题中的抽象属性仅建议使用@property和的答案@abstractmethod:它不能回答我的问题。

通过抽象类属性的ActiveState配方AbstractAttribute可能是正确的方法,但是我不确定。它也仅适用于类属性,不适用于实例属性。

关注者
0
被浏览
43
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    如果您确实想强制子类定义给定的属性,则可以使用元类。就我个人而言,我认为这可能是矫kill过正,不是很Python,但是您可以执行以下操作:

     class AbstractFooMeta(type):
    
         def __call__(cls, *args, **kwargs):
             """Called when you call Foo(*args, **kwargs) """
             obj = type.__call__(cls, *args, **kwargs)
             obj.check_bar()
             return obj
    
    
     class AbstractFoo(object):
         __metaclass__ = AbstractFooMeta
         bar = None
    
         def check_bar(self):
             if self.bar is None:
                 raise NotImplementedError('Subclasses must define bar')
    
    
     class GoodFoo(AbstractFoo):
         def __init__(self):
             self.bar = 3
    
    
     class BadFoo(AbstractFoo):
         def __init__(self):
             pass
    

    基本上,重新定义元类__call__以确保 check_bar在实例的init之后被调用。

    GoodFoo()  # ok
    BadFoo ()  # yield NotImplementedError
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看