抽象属性(不是属性)? [英] Abstract attribute (not property)?

查看:18
本文介绍了抽象属性(不是属性)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What's the best practice to define an abstract instance attribute, but not as a property?

我想写一些类似的东西:

I would like to write something like:

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__ 中).

Properties are handy, but for simple attribute requiring no computation they are an overkill. This is especially important for abstract classes which will be subclassed and implemented by the user (I don't want to force someone to use @property when he just could have written self.foo = foo in the __init__).

Python 中的抽象属性 问题建议作为使用 @property<的唯一答案/code> 和 @abstractmethod:它没有回答我的问题.

Abstract attributes in Python question proposes as only answer to use @property and @abstractmethod: it doesn't answer my question.

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

The ActiveState recipe for an abstract class attribute via AbstractAttribute may be the right way, but I am not sure. It also only works with class attributes and not instance attributes.

推荐答案

如果你真的想强制子类定义一个给定的属性,你可以使用元类:

If you really want to enforce that a subclass define a given attribute, you can use metaclasses:

 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 之后被调用.

Basically the meta class redefine __call__ to make sure check_bar is called after the init on an instance.

GoodFoo()  # ok
BadFoo ()  # yield NotImplementedError

这篇关于抽象属性(不是属性)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆