简体   繁体   English

在装饰器内扩展Python中的类

[英]Extending a class in Python inside a decorator

I am using a decorator to extend certain classes and add some functionality to them, something like the following: 我正在使用装饰器来扩展某些类并为它们添加一些功能,如下所示:

def useful_stuff(cls):
  class LocalClass(cls):
    def better_foo(self):
      print('better foo')
  return LocalClass

@useful_stuff
class MyClass:
  def foo(self):
    print('foo')

Unfortunaltely, MyClass is no longer pickleable due to the non global LocalClass Unfortunaltely,MyClass的是不再与pickle由于非全球LocalClass

AttributeError: Can't pickle local object 'useful_stuff.<locals>.LocalClass'
  • I need to pickle my classes. 我需要挑选我的课程。 Can you recommend a better design? 你能推荐一个更好的设计吗?
  • Considering that there can be multiple decorators on a class, would switching to multiple inheritance by having MyClass inherit all the functionality be a better option? 考虑到类上可以有多个装饰器,通过让MyClass继承所有功能是一个更好的选择,可以切换到多重继承吗?

You need to set the metadata so the subclass looks like the original: 您需要设置元数据,以便子类看起来像原始的:

def deco(cls):
    class SubClass(cls):
        ...
    SubClass.__name__ = cls.__name__
    SubClass.__qualname__ = cls.__qualname__
    SubClass.__module__ = cls.__module__
    return SubClass

Classes are pickled by using their module and qualname to record where to find the class. 通过使用他们的模块和qualname来记录类,以记录在哪里找到类。 Your class needs to be found in the same location the original class would have been if it hadn't been decorated, so pickle needs to see the same module and qualname. 如果没有装饰,你的类需要在原始类所在的位置找到,因此pickle需要查看相同的模块和qualname。 This is similar to what funcutils.wraps does for decorated functions. 这类似于funcutils.wraps对装饰函数的作用。

However, it would probably be simpler and less bug-prone to instead add the new methods directly to the original class instead of creating a subclass: 但是,它可能更简单,更不容易出错,而是将新方法直接添加到原始类而不是创建子类:

def better_foo(self):
    print('better_foo')

def useful_stuff(cls):
    cls.better_foo = better_foo
    return cls

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM