英文:
Implement abstract properties without redefining __init__ in child
问题
我正在学习abc
模块,想知道我想做的是否可能。
基本上,我创建的每个子类都应该具有完全相同的__init__
。基类将具有一些需要由子类定义的抽象属性。我想在不必每次都重写整个__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 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 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
对于最后一个尝试,如果你在父类的__init__
中设置断点并执行dir(self)
,你会看到其中包含了'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"
以这种方式做有问题吗?
英文:
I am learning the abc
module and was wondering if what I want to do is possible.
Essentially, every child I make of the base class should have the SAME exact __init__
. The base class will have a few abstract properties that will need to be defined by the child. I would to define those abstract properties without having to rewrite the entire __init__
every time.
Example:
I initially tried something like this
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'
it didn't work.
Then I tried
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
Test
>>> 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
No good either, so then I tried
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
test
>>> 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
For the last one if you set a breakpoint in __init__
of the parent and do a dir(self)
you'll see 'prop'
in it.
>>> 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']
So I thought that would work.
Edit:
I see I am completely over complicating this. I could have simply did
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"
Is there an issue with doing it this way?
答案1
得分: 1
正如您正确总结的那样,最简单的解决方案是定义一个abstractproperty
,并让子类定义它,根本不需要__init__
。
我会更进一步,在基类中引发一个异常,以确保没有不必要的super()
调用。
import abc
class test(abc.ABC):
@property
@abc.abstractmethod
def prop(self):
raise NotImplementedException()
class prop_ex(test):
prop = "THIS WORKS"
顺便说一句:您的第一个示例已经对我起作用。其他两个不起作用的原因是,第二种方法尝试查找一个名为prop
的局部变量,而这个变量不存在,第三种方法在类体中引用了**self
** - 但是self
只在类的方法/属性中定义,而不在类体中。
此外,这并不阻止子类修改__init__
,任何子类仍然可以修改__init__
。
英文:
As you've correctly summized, the most straight-forward solution would be to define an abstractproperty
and simply let the subclass define it, no need for __init__
at all.
I would go a step further and throw an Exception in the base-class just to make sure there's no stray super()
call on it.
import abc
class test(abc.ABC):
@property
@abc.abstractmethod
def prop(self):
raise NotImplementedException()
class prop_ex(test):
prop = "THIS WORKS"
By the way: Your first example already worked for me. The other two don't work because the second approach tries to find a local variable called prop
which doesn't exist and the third approach references self
in the class body - but self
is only defined in methods/properties of a class, not in the class body.
Also this doesn't prevent __init__
from being overridden in subclasses, any subclass may still modify the __init__
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论