gpt4 book ai didi

python - 强制在所有继承类中实现一个方法

转载 作者:太空宇宙 更新时间:2023-11-03 13:43:17 25 4
gpt4 key购买 nike

我有一种情况,我想强制每个继承自某个(抽象)类的类来实现一个方法。这是我通常会使用@abstractmethod 实现的。但是,考虑到这种多重继承的情况:

from abc import ABCMeta, abstractmethod
class A(object):
__metaclass__ = ABCMeta

@abstractmethod
def very_specific_method(self):
pass

class B(A):
def very_specific_method(self):
print 'doing something in B'

class C(B):
pass

我也想强制执行 C 来实现该方法。我希望每个直接或间接继承 A 的类都被迫实现该方法。这可能吗?

澄清:我希望它适用于特定方法,而不是所有抽象方法。抽象方法应该继续以同样的方式工作,但也许应该创建一个新的装饰器来指示不同类型的方法。

旁注:我在问题中使用了 abc,因为这似乎与问题最相关。我了解抽象方法通常如何工作并定期使用它们。这是不同的情况,如果不是通过 abc 完成,我不介意。

最佳答案

ABCMeta 的修改版本应该可以解决问题。

在这里,我们可以检查基类中 __isabstractmethod__ 设置为 True 的方法,而不是检查它是否在类的 MRO 中,以及是否在任何MRO 中的类,但它不存在于当前类中,那么我们可以将其添加到集合 abstracts 中。

from abc import ABCMeta, abstractmethod
from _weakrefset import WeakSet

class EditedABCMeta(ABCMeta):

def __new__(mcls, name, bases, namespace):
cls = type.__new__(mcls, name, bases, namespace)
# Compute set of abstract method names
abstracts = set(name
for name, value in namespace.items()
if getattr(value, "__isabstractmethod__", False))

for base in cls.__mro__:
for name, value in base.__dict__.items():
if getattr(value, "__isabstractmethod__", False) and name not in cls.__dict__:
abstracts.add(name)

cls.__abstractmethods__ = frozenset(abstracts)
# Set up inheritance registry
cls._abc_registry = WeakSet()
cls._abc_cache = WeakSet()
cls._abc_negative_cache = WeakSet()
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
return cls

class A(object):
__metaclass__ = EditedABCMeta

@abstractmethod
def veryspecificmethod(self):
pass

class B(A):
def veryspecificmethod(self):
print 'doing something in B'

@abstractmethod
def foo(self):
print 'foo from B'

class C(B):
def foo(self):
pass

class D(C, B):
pass

if __name__ == '__main__':
for cls in (C, D):
try:
cls().veryspecificmethod
except TypeError as e:
print e.message
print '-'*20
for cls in (C, D):
try:
cls().foo
except TypeError as e:
print e.message

输出:

Can't instantiate abstract class C with abstract methods veryspecificmethod
Can't instantiate abstract class D with abstract methods foo, veryspecificmethod
--------------------
Can't instantiate abstract class C with abstract methods veryspecificmethod
Can't instantiate abstract class D with abstract methods foo, veryspecificmethod

编辑:

在不影响@abstractmethod的情况下,添加一个特殊的装饰器@enforcedmethod:

from abc import ABCMeta, abstractmethod

def enforcedmethod(func):
func.__enforcedmethod__ = True
return func

class EditedABCMeta(ABCMeta):

def __call__(cls, *args, **kwargs):

enforcedmethods = set()
for base in cls.__mro__:
for name, value in base.__dict__.items():
if getattr(value, "__enforcedmethod__", False) and name not in cls.__dict__:
enforcedmethods.add(name)
if enforcedmethods:
raise TypeError("Can't instantiate abstract class {} "
"with enforced methods {}".format(
cls.__name__, ', '.join(enforcedmethods)))
else:
return super(EditedABCMeta, cls).__call__(*args, **kwargs)

class A(object):
__metaclass__ = EditedABCMeta

@enforcedmethod
def veryspecificmethod(self):
pass
@abstractmethod
def simplemethod(self):
pass

class B(A):
def veryspecificmethod(self):
print 'doing something in B'
def simplemethod(self):
pass

class C(B):
pass

class D(C):
def veryspecificmethod(self):
print 'doing something in D'

输出:

>>> D().veryspecificmethod()
doing something in D
>>> C().veryspecificmethod()

Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
C().veryspecificmethod()
File "C:\Python27\so.py", line 19, in __call__
cls.__name__, ', '.join(enforcedmethods)))
TypeError: Can't instantiate abstract class C with enforced methods veryspecificmethod

关于python - 强制在所有继承类中实现一个方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25649909/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com