листинг типа объекта в Python после перезагрузки модуля?

Я запускаю интерактивный сеанс python, который строит большие структуры данных python (5+ ГБ), которые занимают много времени для загрузки, и поэтому я хочу максимально использовать возможности изменения кода на Python на максимальном уровне (хотя иногда, без нужно слишком много планировать для этого ).

Моя текущая проблема заключается в следующем: у меня есть старый экземпляр класса, который позже модифицировал код и перезагрузил модуль. Я бы хотел, чтобы старый экземпляр мог использовать новые определения функций. Как мне это сделать без ручного копирования всей информации из старого экземпляра в новый новый экземпляр?

Вот что я пробовал. Предположим, что у меня есть модуль M.py :

 class A(): def f(self): print "old class" 

Вот интерактивный сеанс:

 import M old_a = Ma() # [suppose now I change the definition of MAf in the source file] reload(M) # I attempt to use the new class definition with the old instance: MAf(old_a) 

в этот момент я получаю следующую ошибку типа из Python:

 TypeError: unbound method f() must be called with A instance as first argument (got A instance instead) 

Python, очевидно, не рад получить старый экземпляр A, хотя они в основном функционально эквивалентны (в моем коде) – есть ли способ, которым я мог бы «набирать» его на новый тип экземпляра, чтобы Python не жаловался ? Что-то морально нравится: MAf( (MA) old_a ) ?

В Python нет кастингов, но вы можете изменить класс существующего объекта: он совершенно легален и выполняет работу:

 old_a.__class__=MA old_a.f() 

Пока вы не изменили отношения между методами класса и переменными экземпляра, изменили то, что делает __init__ или что-то в этом роде, это прекрасно.

EDIT: Как указывает jsbueno : методы __init__ или __new__ не вызываются в момент изменения __class__ . Кроме того, новый __del__ будет вызван при уничтожении.

Так как вы не можете бросить, вам нужно пересмотреть свой код, чтобы эти загадочные изменения «на лету» могли работать.

Шаг 1. Отделите алгоритм от данных. Напишите очень простой (и очень маловероятный для изменения) класс для необработанных Данных. Часто список названных кортежей – это все, что вам когда-либо понадобится.

Шаг 2. Создайте алгоритмы, которые работают над объектами данных, «обертывая» их, а не «обновляя» их.

Как это.

 def some_complex_algo( list_of_named_tuples ): for item in list_of_named_tuples: # some calculation yield NewTuple( result1, result2, ..., item ) 

Теперь вы можете попробовать свою обработку:

 result = list( some_complex_algo( source_data ) ) 

Если вам не нравится результат, вам нужно только переопределить ваш some_complex_algo и повторить его. source_data нетронутый. Действительно, это может быть неизменным.