Python 继承非抽象类并将其所有函数转换为抽象方法
我得到了一个上游接口,它的所有函数都定义为非抽象的,而实际上它们应该用Python 继承非抽象类并将其所有函数转换为抽象方法,python,inheritance,abstract-class,Python,Inheritance,Abstract Class,我得到了一个上游接口,它的所有函数都定义为非抽象的,而实际上它们应该用@abstractmethods来修饰。当调用它时,我没有实现它的一个函数时,我希望收到一个错误。为此,我将创建一个包装器类,手动遍历其定义的每个函数,并执行如下操作: from abc import ABC, abstractmethod class Foo(object): def foo(self): print("Foo") class AbstractFoo(Foo, ABC):
@abstractmethod
s来修饰。当调用它时,我没有实现它的一个函数时,我希望收到一个错误。为此,我将创建一个包装器类,手动遍历其定义的每个函数,并执行如下操作:
from abc import ABC, abstractmethod
class Foo(object):
def foo(self):
print("Foo")
class AbstractFoo(Foo, ABC):
@abstractmethod
def foo(self):
return super().foo()
class ConcreteFoo(AbstractFoo):
def foo(self):
print("Concrete Foo")
super().foo()
f = ConcreteFoo()
f.foo()
哪些产出:
Concrete Foo
Foo
我想对Foo定义的所有函数都这样做。显然,像\uuuu str\uuuu
和\uuuu repr\uuuu
这样的继承魔法函数应该被适当地转发
有人知道一个好的,蟒蛇式的方法吗
def validate_base_class_implemntation(cls):
base_cls_funcs = []
for attr in cls.__bases__[0].__dict__:
if callable(getattr(cls, attr)):
base_cls_funcs.append(attr)
cls_funcs = []
for attr in cls.__dict__:
if callable(getattr(cls, attr)):
cls_funcs.append(attr)
missing_funcs = [x for x in base_cls_funcs if x not in cls_funcs]
if len(missing_funcs) > 0:
print("Not implemented functions are: {}".format(','.join(missing_funcs)))
raise Exception("Not implement function exception!")
return cls
class Foo(object):
def foo(self):
print("Foo")
def boo(self):
print("Wow")
@validate_base_class_implemntation
class ConcreteFoo(Foo):
def foo(self):
print("Concrete Foo")
super().foo()
f = ConcreteFoo()
f.foo()
100%不确定这是否是你的意思
这个装饰器检查被装饰的类是否实现了所有的基类函数(在您的例子中,它们没有被抽象装饰)。如果修饰类未实现某个函数,则会引发异常。您可以修改原始类
Foo
,并将其所有方法转换为抽象方法,然后使用metaclass=ABCMeta
定义Foo
的空白子类,以处理检查:
from abc import ABCMeta, abstractmethod
from types import FunctionType
class AbstractFoo(Foo, metaclass=ABCMeta):
pass
names = set()
for k, v in vars(Foo).items():
if k.startswith('__') and k.endswith('__'):
continue
elif isinstance(v, FunctionType):
names.add(k)
v.__isabstractmethod__ = True
AbstractFoo.__abstractmethods__ = frozenset(names)
旁注:此方法依赖于abc使用的dunder属性,因此可以在不受反对的情况下中断。m。。。我有一个使用decorator的主意,对你有效吗?意思是不在运行时感谢您的实现!在问题陈述中,我应该提到
Foo
可能没有直接继承对象
,这意味着可能存在我不想抽象的非dunders。这将适用于所有功能。不过,我对你的答案投了赞成票!为不完整的内容道歉specification@OneRaynyDay我不太明白你的意思vars(Foo)
只检查Foo
的立即属性,不包括任何基类。如果Foo
本身定义了你不想抽象的方法,那么对于任何算法,你都需要为它们提供一些规范。这对我很有用!非常感谢您的实施。我想知道是否有一种更像蟒蛇的方式来做到这一点,但这对我来说已经足够了:)干杯@每天我都会考虑it@OneRaynyDay更具pythonic:(1)对函数使用set
而不是list
,然后使用missing_funcs=base_cls_funcs-cls_funcs
,(2)检查如果missing_funcs
就足够了,(3)使用cls.mro()[1]
而不是cls.[0]
,(4)使用vars(…)
而不是,(5)对循环使用理解而不是两个,(6)提出类型错误而不是异常
。可调用的将包括非函数对象,因此isinstance(…,types.FunctionType)
更合适。