如何强制在类定义中设置属性

时间:2018-03-05 20:08:17

标签: python python-3.x abstract-class abc

我想创建一个抽象类,以便子类在实例化时如果不实现抽象属性则会引发错误。如果属性是方法而不是属性,也应该引发错误。我的尝试:

from abc import ABC, abstractmethod
class IClass(ABC):
    @property
    @abstractmethod
    def attr(self):
        pass

不幸的是,这无法阻止使用attr方法而不是属性来实例化子类。

解决方案应该产生以下结果:

class C(IClass):
    pass
C()  # Must fail because 'attr' has not been implemented

class C(IClass):
    def attr(self):
        pass
C().attr  # Must fail because attribute 'attr' is a method rather than a property

class C(IClass):
    attr = 'attr'
C().attr  # Must pass because 'attr' is a property

手册:docs

1 个答案:

答案 0 :(得分:0)

这不像装饰器那样方便,但您可以验证该属性是__new__中的属性,如:

代码:

from abc import ABC, abstractmethod

class IClass(ABC):
    def __new__(cls, *args, **kwargs):
        new = super().__new__(cls, *args, **kwargs)
        if not isinstance(type(new).attr, property):
            raise TypeError('attr must be a property')
        return new

    @property
    @abstractmethod
    def attr(self):
        pass

测试代码:

class A(IClass):
    pass
try:
    # Must fail because 'attr' has not been implemented
    A()
except Exception as exc:
    print('A Passed: {}'.format(exc))

class B(IClass):
    def attr(self):
        pass
try:
    # Must fail because attribute 'attr' is a method rather than a property
    B()
except Exception as exc:
    print('B Passed: {}'.format(exc))

class C(IClass):
    @property
    def attr(self):
        return 'Good'

# Must pass because 'attr' is a property
print('C Passed: {}'.format(C().attr))

结果:

A Passed: Can't instantiate abstract class A with abstract methods attr
B Passed: attr must be a property
C Passed: Good