假设我需要实现一个抽象的Python接口,然后它将有许多派生类(每个类的名字相同,但写在不同的模块中),在基类中,我注意有一个共同的方法,它将使用特定导入的派生类的静态方法。
所以我的玩具模块是这样的。
abstract_class.py
from abc import ABCMeta, abstractmethod
from derived_class import Derived
class Abstract:
__metaclass__ = ABCMeta
@abstractmethod
def foo(self):
pass
def bar(self):
Derived.foo()
派生类.py
from abstract_class import Abstract
class Derived(Abstract):
@staticmethod
def foo():
print 'Good news everyone!'
if __name__ == '__main__':
derived_object = Derived()
derived_object.bar()
然后当然,当我试图运行 derived_class.py
,我得到了抽象名称导入错误。
我如何正确组织这个问题?
... 在基类中,我需要有一个共同的方法,它将使用一个特定的导入派生类的静态方法。
如果我对你的问题理解正确的话,我会说这个功能是开箱即用的,但有一个小例外。不要使用静态方法,只需使用普通的实例方法。
在基类中定义一个抽象方法,将确保派生类包含该方法的实现。而且,开箱即用,在派生类中定义的方法会在你调用 derived_object.bar()
.
另一方面,如果你绝对需要在没有对象实例的情况下做这件事,可以用classmethods而不是staticmethods来做。
from abc import ABC, abstractmethod
class MyAbstractClass(ABC):
@staticmethod
@abstractmethod
def foo(label: str):
raise NotImplementedError()
@classmethod
def foo_agnostic(cls, label: str):
"""
NOTE: Here, this method doesn't have a reference to an instance of the class.
Instead, it only has a reference to the class itself; but that is enough
to call the abstract static foo() method.
"""
cls.foo(label)
class MyDerivedClass(MyAbstractClass):
@staticmethod
def foo(label: str):
print(label)
if __name__ == "__main__":
instance = MyDerivedClass()
instance.foo("Test 1") # Outputs "Test 1"
instance.foo_agnostic("Test 2") # Outputs "Test 2"
MyDerivedClass.foo_agnostic("Test 3") # Outputs "Test 3"