【问题标题】:Python: can I use a class-level decorator to add a mixin to the decorated class?Python:我可以使用类级装饰器向装饰类添加 mixin 吗?
【发布时间】:2021-04-15 15:42:50
【问题描述】:

我想要一个装饰器,除其他外,向它正在装饰的类添加一个 mixin。 (我承认这可能是一个非常糟糕的主意,但请耐心等待。)以下几乎可行:

def add_mixin(cls):
   class inner(cls, NewMixin):
      pass
   return inner

现在如果我这样做:

@add_mixin
class foo:
   ...bunch o' stuff...

foo 类似乎工作得很好,混合了NewMixin。(也许这个方案在面对其他超类时不会完全保留foo 的 MRO,但我认为我不在乎那个。)

我发现的唯一问题是,此时foo.__name__"inner",我希望它是"foo"!我可以通过添加来解决这个问题 inner.__name__ = cls.__name__add_mixin 的定义中,这似乎涵盖了所有基础(实际上)。

问题:有没有更好的方法来做到这一点?这里还有其他我没有看到的潜伏陷阱吗?

感谢您的帮助。

【问题讨论】:

  • 我不确定我是否看到使用装饰器比直接添加 mixin 的好处。它更简单,并且不会向 MRO 添加无意义的包装类。
  • 您是否尝试在新类中明确修补它?
  • @chepner 我假设(希望)装饰器的目的不仅仅是只是添加 mixin,但添加 mixin 是与问题。
  • “在其他东西中”可能是让这个问题变得有趣的原因。

标签: python decorator superclass


【解决方案1】:

编辑:在我写答案时,对问题进行了编辑以提及这种方法。

你可以这样做:

def add_mixin(cls):
   class inner(cls, NewMixin):
      pass
   inner.__name__ = cls.__name__
   return inner

然后:

@add_mixin
class foo:
   pass

@add_mixin
class bar:
   pass

f = foo
print(f.__name__)
b = bar
print(b.__name__)
print(f.__name__)

给予

foo
bar
foo

(在引用 bar 后再次打印 foo 以证明 __name__ 没有被覆盖。)

就陷阱而言,我不确定。

【讨论】:

  • 谢谢。我想得太晚了,就在你写评论的时候自己添加了。请注意,不需要添加变量 i,您可以说 inner.__name__ = cls.__name__。另请注意,您不能在内部定义中执行此操作:仅说 name = cls.__name__ 不起作用;不知道为什么。
  • 哦,对了,因为你仍然可以只返回内部。我会进行调整,所以答案会更简洁一些,虽然它不再是一个有用的答案:) 我的第一次尝试只是尝试直接设置 __name__ ,但它没有像你提到的那样工作。
  • 我接受了您的回答,因为它是正确的。然而,我确实发现了一个陷阱,我将提出另一个问题。完成后我会回到这里并提供一个指针。
猜你喜欢
  • 1970-01-01
  • 2012-08-14
  • 2021-07-16
  • 1970-01-01
  • 2012-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-28
相关资源
最近更新 更多