无需在 child 中重新定义 __init__ 即可实现抽象属性
Implement abstract properties without redefining __init__ in child
我正在学习 abc
模块,想知道我想做的事情是否可行。
基本上,我用基础 class 制作的每个 child 都应该具有完全相同的 __init__
。基础 class 将具有一些需要由 child 定义的抽象属性。我会定义那些抽象属性,而不必每次都重写整个 __init__
。
示例:
我最初尝试过这样的事情
from abc import ABC,abstractmethod
class test(ABC):
def __init__(self):
pass
@property
@abstractmethod
def prop(self):
pass
class prop_ex(test):
@property
def prop(self):
return "THIS WORKS"
>>> from abc_tests import prop_ex
>>> blah = prop_ex()
>>> blah.prop
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'prop_ex' object has no attribute 'prop'
没用。
然后我试了
from abc import ABC,abstractmethod
class test(ABC):
def __init__(self):
self.prop = prop
@property
@abstractmethod
def prop(self):
pass
class prop_ex(test):
prop = "THIS WORKS"
@property
def prop(self):
return self._prop
测试
>>> from abc_tests import prop_ex
>>> blah = prop_ex()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "abc_tests.py", line 13, in __init__
self.prop = prop
NameError: name 'prop' is not defined
也不好,于是试了一下
from abc import ABC,abstractmethod
class test(ABC):
def __init__(self):
pass
@property
@abstractmethod
def prop(self):
pass
class prop_ex(test):
self.prop = "THIS WORKS"
@property
def prop(self):
return self._prop
测试
>>> from dunder_tests import prop_ex
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "abc_tests.py", line 39, in <module>
class prop_ex(test):
File "abc_tests.py", line 40, in prop_ex
self.prop = "THIS WORKS"
NameError: name 'self' is not defined
对于最后一个,如果您在 parent 的 __init__
中设置断点并执行 dir(self)
,您将在其中看到 'prop'
。
>>> blah = prop_ex()
> abc_tests.py(14)__init__()
-> self.prop = prop
(Pdb) dir(self)
['__abstractmethods__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__weakref__', '_abc_impl', 'prop']
所以我认为这行得通。
编辑:
我发现我完全把它复杂化了。我本可以简单地做
from abc import ABC,abstractmethod
class test(ABC):
def __init__(self):
pass
@property
@abstractmethod
def prop(self):
pass
class prop_ex(test):
prop = "THIS WORKS"
这样做有问题吗?
正如您正确总结的那样,最直接的解决方案是定义一个 abstractproperty
并简单地让 subclass 定义它,不需要 __init__
全部.
我会更进一步,在 base-class 中抛出一个异常,只是为了确保没有杂散的 super()
调用它。
import abc
class test(abc.ABC):
@property
@abc.abstractmethod
def prop(self):
raise NotImplementedException()
class prop_ex(test):
prop = "THIS WORKS"
顺便说一句:你的第一个例子已经对我有用了。其他两个不起作用,因为第二种方法试图找到一个名为 prop
的 局部变量,该变量不存在,而第三种方法引用 self
在 class 正文中 - 但 self
仅在 class 的 methods/properties 中定义,而不是在 class 正文中定义。
此外,这不会阻止 __init__
在子 class 中被覆盖,任何子 class 仍然可以修改 __init__
.
我正在学习 abc
模块,想知道我想做的事情是否可行。
基本上,我用基础 class 制作的每个 child 都应该具有完全相同的 __init__
。基础 class 将具有一些需要由 child 定义的抽象属性。我会定义那些抽象属性,而不必每次都重写整个 __init__
。
示例:
我最初尝试过这样的事情
from abc import ABC,abstractmethod
class test(ABC):
def __init__(self):
pass
@property
@abstractmethod
def prop(self):
pass
class prop_ex(test):
@property
def prop(self):
return "THIS WORKS"
>>> from abc_tests import prop_ex
>>> blah = prop_ex()
>>> blah.prop
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'prop_ex' object has no attribute 'prop'
没用。
然后我试了
from abc import ABC,abstractmethod
class test(ABC):
def __init__(self):
self.prop = prop
@property
@abstractmethod
def prop(self):
pass
class prop_ex(test):
prop = "THIS WORKS"
@property
def prop(self):
return self._prop
测试
>>> from abc_tests import prop_ex
>>> blah = prop_ex()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "abc_tests.py", line 13, in __init__
self.prop = prop
NameError: name 'prop' is not defined
也不好,于是试了一下
from abc import ABC,abstractmethod
class test(ABC):
def __init__(self):
pass
@property
@abstractmethod
def prop(self):
pass
class prop_ex(test):
self.prop = "THIS WORKS"
@property
def prop(self):
return self._prop
测试
>>> from dunder_tests import prop_ex
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "abc_tests.py", line 39, in <module>
class prop_ex(test):
File "abc_tests.py", line 40, in prop_ex
self.prop = "THIS WORKS"
NameError: name 'self' is not defined
对于最后一个,如果您在 parent 的 __init__
中设置断点并执行 dir(self)
,您将在其中看到 'prop'
。
>>> blah = prop_ex()
> abc_tests.py(14)__init__()
-> self.prop = prop
(Pdb) dir(self)
['__abstractmethods__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__weakref__', '_abc_impl', 'prop']
所以我认为这行得通。
编辑:
我发现我完全把它复杂化了。我本可以简单地做
from abc import ABC,abstractmethod
class test(ABC):
def __init__(self):
pass
@property
@abstractmethod
def prop(self):
pass
class prop_ex(test):
prop = "THIS WORKS"
这样做有问题吗?
正如您正确总结的那样,最直接的解决方案是定义一个 abstractproperty
并简单地让 subclass 定义它,不需要 __init__
全部.
我会更进一步,在 base-class 中抛出一个异常,只是为了确保没有杂散的 super()
调用它。
import abc
class test(abc.ABC):
@property
@abc.abstractmethod
def prop(self):
raise NotImplementedException()
class prop_ex(test):
prop = "THIS WORKS"
顺便说一句:你的第一个例子已经对我有用了。其他两个不起作用,因为第二种方法试图找到一个名为 prop
的 局部变量,该变量不存在,而第三种方法引用 self
在 class 正文中 - 但 self
仅在 class 的 methods/properties 中定义,而不是在 class 正文中定义。
此外,这不会阻止 __init__
在子 class 中被覆盖,任何子 class 仍然可以修改 __init__
.