【问题标题】:How to use class decorators with pickle?如何将类装饰器与泡菜一起使用?
【发布时间】:2016-03-19 02:37:40
【问题描述】:

我想使用类装饰器(不是函数装饰器!),例如

def class_decorator(cls):
    class new_cls(cls):
        def run(self, *args, **kwargs):
            print 'In decorator'
            super(new_cls,self).run(*args, **kwargs)
    return new_cls

@class_decorator
class cls(object):
    '''
    a class
    '''
    def run(self):
        print 'called'

并且能够腌制物体:

import pickle

a = cls()
a.run()
s = pickle.dumps(a)

但是pickle返回错误:

PicklingError: Can't pickle <class '__main__.new_cls'>: it's not found as __main__.new_cls

任何帮助将不胜感激!

【问题讨论】:

    标签: python class decorator pickle


    【解决方案1】:

    当您腌制课程时,the name of the class -- not its value -- is pickled。如果class_decorator 返回一个新类,其 name 未在 模块的顶层,然后你会得到错误:

    PicklingError: Can't pickle <class '__main__.new_cls'>: it's not found as __main__.new_cls 
    

    您可以通过将新的装饰类命名为与未装饰的类相同的方式来避免错误:

    new_cls.__name__ = cls.__name__
    

    然后代码运行无误:

    import pickle
    
    def class_decorator(cls):
        class new_cls(cls):
            def run(self, *args, **kwargs):
                print 'In decorator'
                super(new_cls,self).run(*args, **kwargs)
        new_cls.__name__ = cls.__name__
        return new_cls
    
    @class_decorator
    class cls(object):
        def run(self):
            print 'called'
    
    a = cls()
    print(a)
    # <__main__.cls object at 0x7f57d3743650>
    
    a.run()
    # In decorator
    # called
    
    s = pickle.dumps(a)
    # Note "cls" in the `repr(s)` below refers to the name of the class. This is
    # what `pickle.loads` is using to unpickle the string
    print(repr(s))
    # 'ccopy_reg\n_reconstructor\np0\n(c__main__\ncls\np1\nc__builtin__\nobject\np2\nNtp3\nRp4\n.'
    
    b = pickle.loads(s)
    print(b)
    # <__main__.cls object at 0x7f57d3743690>
    
    b.run()
    # In decorator
    # called
    

    【讨论】:

    • 这在 Python 2 中运行良好,但在 Python 3 中似乎失败:AttributeError: Can't pickle local object 'class_decorator.&lt;locals&gt;.new_cls'
    猜你喜欢
    • 2020-02-25
    • 2018-01-22
    • 1970-01-01
    • 2016-09-12
    • 2012-12-17
    • 2018-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多