繁体   English   中英

Python:在类中创建抽象静态属性

[英]Python: Create Abstract Static Property within Class

我真正想做的是这样的:

class X(metaclass=abc.ABCMeta):
    @abc.abstractAttribute # this doesn't exist
    var = [1,2]

class Y(X):
    var = X.var + [3,4]

这将强制X的任何子类实现静态var属性。

但是没有办法将静态属性定义为抽象的。

尝试使用@abc.abstractmethod,结合属性,我可以接近:

class X(metaclass=abc.ABCMeta):
    @property
    @abc.abstractmethod
    def var(self):
        return [1,2]

class Y(X):
    @property
    def var(self):
        return super().var + [3,4]

y=Y(); y.var y=Y(); y.var根据需要给出[1,2,3,4]

但目标是创建静态属性/属性,而不是实例属性/属性。

创建为 @staticmethod 时:

class X(metaclass=abc.ABCMeta):
    @property
    @staticmethod
    @abc.abstractmethod
    def var():
        return [1,2]

class Y(X):
    @property
    @staticmethod
    def var():
        return X.var + [3,4]

... 然后y=Y(); y.var y=Y(); y.var给出TypeError 'staticmethod' object is not callable

如果我切换装饰器顺序,这将解决 staticmethod 可调用错误:

class X(metaclass=abc.ABCMeta):
    @staticmethod
    @property
    @abc.abstractmethod
    def var():
        return [1,2]

class Y(X):
    @staticmethod
    @property
    def var():
        return X.var + [3,4]

静态方法可以工作,但属性不会按预期运行: y=Y(); y.var y=Y(); y.var返回属性本身, <property at 0x2c16aa1b3b8>

这个答案接近于所期望的,但在这种情况下它不起作用,因为基类X已经具有var属性(因此子类可以通过 super 访问)。

你如何定义一个 python 类来拥有一个抽象的、静态的属性/特性?

如果它是一个属性的要求是灵活的,你可以只定义一个静态抽象方法:

class X:
  @staticmethod
  @abstractmethod
  def var():
    pass

class Y(X):
  @staticmethod
  def var():
    return [1, 2]

>>> Y.var()
[1, 2]

也许您的解决方案的变体可以工作 - 而不是使用dict简单地测试父类和子类的静态变量是否是同一个对象。 它适用于孙子和插槽,但权衡是如果您用 None 覆盖 None 或具有相同对象的其他对象,它会抛出异常,因此它并不完美。

class X:
var = [1,2]

def __init_subclass__(cls):
    if X.var is cls.var:
        raise NotImplementedError(
            "Attribute '{}' has not been overriden in class '{}'" \
            .format('var', cls.__name__)
        )

也许我忽略了一些重要的东西,但它在简单的用例中起作用。

这建立在使用__init_subclass__的其他答案的方法之上。 它在除X本身之外的每个基类中搜索属性(通过其 MRO)。 这解决了未明确覆盖属性的孙子问题。

class X(metaclass=abc.ABCMeta):
    var = [1,2]

    def __init_subclass__(cls):
        if not any("var" in base.__dict__ for base in cls.__mro__ if base is not X):
            raise NotImplementedError(
                f"Attribute 'var' has not been overwritten in class '{cls.__name__}'"
            )

它不解决__slots__ 但是,如果您坚持使用类属性来覆盖抽象属性,那么在您的类中定义__slots__不是问题。

如果您知道解决此问题的更传统方法也适用于使用__slots__的类,请告诉我。 但对于我的用例,以下将起作用:

class X:
    var = [1,2]

    def __init_subclass__(cls):
        attr_name = 'var'
        if not attr_name in cls.__dict__:
            raise NotImplementedError(
                "Attribute '{}' has not been overriden in class '{}'" \
                .format(attr_name, cls.__name__)
            )

class Y(X):
    # var = X.var + [3,4] # this will work
    pass                  # this won't work

y = Y()

编辑:使用这种方法还有另一个缺点,那就是对于不覆盖的孙子来说,这会错误地出错:

class Y(X):
    var = X.var + [3,4]

y = Y() # this works

class Z(Y):
    pass

z = Z() # this errors

我会将此答案保留为未标记,以便有人提出更好的选择。

暂无
暂无

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

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