在装饰器内扩展Python中的类

roh*_*was 4 python pickle python-3.x python-decorators

我正在使用装饰器来扩展某些类并为它们添加一些功能,如下所示:

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')
Run Code Online (Sandbox Code Playgroud)

Unfortunaltely,MyClass的是不再与pickle由于非全球LocalClass

AttributeError: Can't pickle local object 'useful_stuff.<locals>.LocalClass'
Run Code Online (Sandbox Code Playgroud)
  • 我需要挑选我的课程.你能推荐一个更好的设计吗?
  • 考虑到类上可以有多个装饰器,通过让MyClass继承所有功能是一个更好的选择,可以切换到多重继承吗?

use*_*ica 8

您需要设置元数据,以便子类看起来像原始的:

def deco(cls):
    class SubClass(cls):
        ...
    SubClass.__name__ = cls.__name__
    SubClass.__qualname__ = cls.__qualname__
    SubClass.__module__ = cls.__module__
    return SubClass
Run Code Online (Sandbox Code Playgroud)

通过使用他们的模块和qualname来记录类,以记录在哪里找到类.如果没有装饰,你的类需要在原始类所在的位置找到,因此pickle需要查看相同的模块和qualname.这类似于funcutils.wraps装饰函数.

但是,它可能更简单,更不容易出错,而是将新方法直接添加到原始类而不是创建子类:

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

def useful_stuff(cls):
    cls.better_foo = better_foo
    return cls
Run Code Online (Sandbox Code Playgroud)