У меня есть класс (Bar
), который фактически имеет собственное состояние и обратные вызовы и используется другим классом (Foo
):
class Foo(object):
def __init__(self):
self._bar = Bar(self.say, 10)
self._bar.work()
def say(self, msg):
print msg
class Bar(object):
def __init__(self, callback, value):
self._callback = callback
self._value = value
self._more = { 'foo' : 1, 'bar': 3, 'baz': 'fubar'}
def work(self):
# Do some work
self._more['foo'] = 5
self._value = 10
self._callback('FooBarBaz')
Foo()
Очевидно, я не могу выделить класс Foo
, поскольку Bar
имеет метод экземпляра, поэтому у меня осталось следующее решение реализации __getstate__
& __setstate__
в Bar
, чтобы сохранить self._value
и self._more
, но я также должен создать экземпляр метода self._callback
(т.е. вызвать __init__()
из внешнего класса Foo
, передав функцию обратного вызова .
Но я не могу понять, как этого добиться.
Любая помощь приветствуется.
Спасибо.
1 ответ
Я думаю, что если вам нужно сериализовать что-то подобное, вам нужно иметь возможность определить обратный вызов как строку. Например, вы можете сказать, что callback = 'myproject.callbacks.foo_callback'
.
Обычно в __getstate__
вы должны заменить функцию _callback
чем-то, что вы могли бы использовать для поиска функции позже, например self._callback.__name__
.
В __setstate__
вы должны заменить _callback
функцией.
Это зависит от того, имеют ли все ваши функции настоящие имена, поэтому вы не можете использовать лямбда в качестве обратного вызова и ожидать, что он будет сериализован. Вам также понадобится разумный механизм для поиска ваших функций по имени.
Вы можете потенциально использовать __import__
(что-то вроде: 'myproject.somemodule.somefunc' синтаксис имени с точками может поддерживаться таким образом, см. http://code.google.com/p/mock/source/browse/mock.py#1076 ) или просто определите таблицу поиска в ваш код.
Просто быстрый (непроверенный, извините!) Пример, предполагающий, что у вас есть небольшой набор возможных обратных вызовов, определенных в таблице поиска:
def a():
pass
callbacks_to_name = {a: 'a'
# ...
}
callbacks_by_name = {'a': a,
# ...
}
class C:
def __init__(self, cb):
self._callback = cb
def __getstate__(self):
self._callback = callbacks_to_name[self._callback]
return self.__dict__
def __setstate__(self, state):
state[_callback] = callbacks_by_name[self._callback]
Я не уверен, каков ваш вариант использования, но я бы рекомендовал сделать это, сериализовав ваши рабочие элементы в JSON или XML и написав простой набор функций для их сериализации и десериализации самостоятельно.
Преимущество состоит в том, что сериализованный формат может быть прочитан и понят людьми и изменен при обновлении программного обеспечения. Pickle заманчиво, потому что кажется достаточно близким, но к тому времени, когда у вас будет серьезная куча __getstate__
и __setstate__
, вы действительно не сэкономите много усилий или головной боли, создавая собственную схему специально для вашего приложения. .
Похожие вопросы
Связанные вопросы
Новые вопросы
python
Python — это мультипарадигмальный многоцелевой язык программирования с динамической типизацией. Он предназначен для быстрого изучения, понимания и использования, а также обеспечивает чистый и унифицированный синтаксис. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Если у вас есть вопросы о версии Python, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas, NumPy) укажите это в тегах.
getattr()
__main__.instancemethod.functionname
вместо отображения имени класса. Какие-либо предложения?__main__
. python.org/dev/peps / pep-0395 / # в рассолеunbound
(и я не могу привязать к нему себя во время выполнения). Я использую собственные методы для сохранения данных и установки их другим методом послеinit()