gpt4 book ai didi

python-3.x - 如何在 Python 中使用类装饰器混合行为?

转载 作者:行者123 更新时间:2023-12-05 02:20:36 26 4
gpt4 key购买 nike

我有一个包含很多直接子类的基类。多个子类共享多个独立的特征。这是 Python 协作继承的一个很好的用例。但是,这些功能应该从外部包装行为,因此它们需要在方法解析顺序中靠前。

class WrappedSub(FeatureA, FeatureB, FeatureC, RealSub):

def __init__(self, *args, **kwargs):
FeatureA.__init__(foo=42)
FeatureB.__init__(bar=13)
FeatureC.__init__(foobar=546)
RealSub.__init__(*args, **kwargs)

class RealSub(Base):
# Lots of code ...

最好装饰子类。

@Mixin(FeatureA, 42)
@Mixin(FeatureB, 13)
@Mixin(FeatureC, 546)
class RealSub(Base):
# Lots of code ...

准确地说,我需要一个 @Mixin 装饰器,其中下面的第一个 block 等同于第二个 block 。

@Mixin(Sub, *feature_args, **feature_kwargs)
class RealSub:
# Lots of code ...

class RealSub:
# Lots of code ...
class WrappedSub(Feature, RealSub):
def __init__(self, *sub_args, **sub_kwargs):
Feature.__init__(self, *feature_args, **feature_kwargs)
RealSub.__init__(self, *sub_args, **sub_kwargs)
RealSub = WrappedSub

这在 Python 3 中如何实现?

最佳答案

您或许可以使用 Python 的协同多重继承系统来编写您的混合类,而不是尝试将它们实现为类装饰器。这就是我对 Python OOP 中使用的术语“mixin”的一般理解。

class Base:
def method(self, param):
value = param + 18
return value

class FeatureOne: # this could inherit from Base
def method(self, param):
if param == 42:
return 13
else:
return super().method(param) # call next class in inheritance chain

class Child(FeatureOne, Base):
def method(self, param):
value = super().method(param)
value *= 2
return value

这与您想要的不太一样,因为它在 Base 之间调用了 FeatureOne 类的 method 实现>Child 类的版本,而不是在 Child 做它的事情之前。如果您不能调整按此顺序工作的方法(Grandchild 类的主体可以为空)。

如果你真的想使用装饰器来翻转顺序,我想你可以让它工作,装饰器为你构建一个“孙子”类(尽管它对正常的继承层次结构一无所知) .这是对 mixin 装饰器的粗略尝试,它几乎可以像您想要的那样工作:

def mixin(*mixin_classes, **mixin_kwargs): # decorator factory function
def decorator(cls): # decorator function
class wrapper(*mixin_classes, cls):
def __init__(self, *args, **kwargs):
wrapped_kwargs = mixin_kwargs.copy() # use the passed kwargs to update the
wrapped_kwargs.update(kwargs) # mixin args, so caller can override
super().__init__(*args, **wrapped_kwargs)
# maybe modify wrapper's __name__, __qualname__, __doc__, etc. to match cls here?
return wrapper
return decorator

mixin 类应该从它们自己的 __init__ 方法(如果它们有一个)调用 super().__init__(*args, **kwargs),但它们可以接受(但不传递)它们自己希望由 mixin 装饰器传递的仅限关键字的参数:

class FeatureOne:
def __init__(self, *args, foo, **kwargs): # note that foo is a keyword-only argument
self.foo = foo
super().__init__(*args, **kwargs)

def method(self, param):
if param == self.foo:
return 13
else:
return super().__method__(param)

@mixin(FeatureOne, foo=42)
class Child(Base):
def method(self, param):
return super().method(param) * 2

装饰器应该与传递给一个装饰器调用的所有混合类一起工作(例如 @mixin(FeatureA, FeatureB, FeatureC, foo=42, bar=13, foobar=546)),或使用多个嵌套的装饰器调用。无论哪种方式,最后一类的 MRO 都是相同的。

关于python-3.x - 如何在 Python 中使用类装饰器混合行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38405619/

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