Вопрос

Я пытался выделить объект, который содержит ссылки на методы статического класса.Рассол не получается (например, на module.MyClass.foo) заявляя, что его нельзя мариновать, так как module.foo не существует.
Я придумал следующее решение, используя объект-оболочку для определения местоположения функции при вызове, сохраняя класс контейнера и имя функции:

class PicklableStaticMethod(object):
    """Picklable version of a static method.
    Typical usage:
        class MyClass:
            @staticmethod
            def doit():
                print "done"
        # This cannot be pickled:
        non_picklable = MyClass.doit
        # This can be pickled:
        picklable = PicklableStaticMethod(MyClass.doit, MyClass)
    """
    def __init__(self, func, parent_class):
        self.func_name = func.func_name
        self.parent_class = parent_class
    def __call__(self, *args, **kwargs):
        func = getattr(self.parent_class, self.func_name)
        return func(*args, **kwargs)

Однако мне интересно, есть ли лучший - более стандартный способ - замариновать такой объект?Я не хочу вносить изменения в глобальную pickle процесс (с использованием copy_reg например), но следующий шаблон был бы отличным:класс MyClass(объект):@picklable_staticmethod определение foo():выведите "готово".

Мои попытки сделать это были безуспешными, в частности, потому, что я не смог извлечь класс owner из foo функция.Я даже был готов согласиться на явное уточнение (например, @picklable_staticmethod(MyClass)) но я не знаю ни о каком способе сослаться на MyClass класс прямо там, где он определяется.

Любые идеи были бы замечательными!

Йонатан

Это было полезно?

Решение

Кажется, это работает.

class PickleableStaticMethod(object):
    def __init__(self, fn, cls=None):
        self.cls = cls
        self.fn = fn
    def __call__(self, *args, **kwargs):
        return self.fn(*args, **kwargs)
    def __get__(self, obj, cls):
        return PickleableStaticMethod(self.fn, cls)
    def __getstate__(self):
        return (self.cls, self.fn.__name__)
    def __setstate__(self, state):
        self.cls, name = state
        self.fn = getattr(self.cls, name).fn

Хитрость заключается в том, чтобы захватить класс, когда из него получен статический метод.

Альтернативы:Вы можете использовать метаклассинг, чтобы придать всем вашим статическим методам .__parentclass__ атрибут.Тогда вы могли бы создать подкласс Pickler и дать каждому экземпляру подкласса свой собственный .dispatch таблицу, которую затем можно изменить, не затрагивая глобальную таблицу диспетчеризации (Pickler.dispatch).Тогда консервирование, распаковка и вызов метода могут выполняться немного быстрее.

Другие советы

Редактировать:изменено после комментария Джейсона.

Я думаю, что python прав, не позволяя травить объект staticmethod - поскольку невозможно травить методы экземпляра или класса!Такой объект имел бы очень мало смысла вне своего контекста:

Проверьте это: Учебное пособие по дескрипторам

import pickle

def dosomething(a, b):
    print a, b

class MyClass(object):
    dosomething = staticmethod(dosomething) 

o = MyClass()

pickled = pickle.dumps(dosomething)

Это работает, и это то, что нужно сделать - определить функцию, настроить ее и использовать такую функцию как staticmethod в определенном классе.

Если у вас есть вариант использования для ваших нужд, пожалуйста, запишите его, и я буду рад обсудить его.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top