Python NotImplementedError for instance attributes
如何将实例属性标记为未在基类中实现? (与讨论将类属性标记为未实现的问题不同,但也许我没有正确理解基类……)
例如我想要类似
的东西
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class Base():
def __init__(self): self.x = NotImplemented class GoodSub(Base): class BadSub(Base): good = GoodSub(5) |
或者,有没有更好的方法来强制 Base 的所有子类在初始化时设置 self.x 属性?
编辑:相关问题的链接
- 请注意,bad.x 不会引发错误,它会返回类 NotImplemented。
- 是的,这正是我想要解决的问题。使用 @property 感觉有点笨拙,特别是如果有很多”抽象实例属性”我想在基类中定义…
一个带有类装饰器和描述符的解决方案(__get__ 方法):
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
def abstract_variables(*args):
class av: def __init__(self, error_message): self.error_message = error_message def __get__(self, *args, **kwargs): def f(klass): return f
@abstract_variables(‘x’, ‘y’) class Derived(Base):
b = Base() |
打印:
1
2 3 4 5 6 7 |
10
Traceback (most recent call last): File“main.py”, line 28, in <module> print(d.y) File“main.py”, line 7, in __get__ raise NotImplementedError(self.error_message) NotImplementedError: Descendants must set variable `y` |
- 我比我支持的 @property 方法更喜欢这个。确保您使用 functools.wraps 以便更好地进行自省。
- @AdamSmith 但是我应该 wrap() 做什么?我按原样返回 klass
我会考虑将 x 设为属性。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
class Base():
def __init__(self): self.__x = None self.__x_is_set = False @property def x(self): if not self.__x_is_set: raise NotImplementedError(‘Descendents from Base must set x’) else: return self.__x @x.setter def x(self, value): self.__x = value self.__x_is_set = True
class GoodSub(Base): class BadSub(Base): class AlsoBad(Base): |
1
2 3 4 5 6 7 8 9 10 11 12 13 |
>>> g, a, b = GoodSub(), BadSub(), AlsoBad()
>>> g.x 5 >>> a.x Traceback (most recent call last): File“<stdin>”, line 1, in <module> File“<stdin>”, line 8, in x NotImplementedError: Descendents from Base must set x >>> b.x Traceback (most recent call last): File“<stdin>”, line 1, in <module> File“<stdin>”, line 8, in x NotImplementedError: Descendents from Base must set x |
- 难道你不能通过使用 hasattr(self, ‘__x’) 而不是 __x_is_set 来简化代码吗?
- @norok2 不,因为对于所有这些子类实例 assert hasattr(self, ‘__x’)。 super().__init__() 创建该属性。
- 你只是没有在基类中定义它
来源:https://www.codenong.com/56997102/