приведение типов объектов в Python после перезагрузки модуля?[для изменения кода на лету] - PullRequest
4 голосов
/ 06 февраля 2012

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

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

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

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

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

import M
old_a = M.a()

# [suppose now I change the definition of M.A.f in the source file]

reload(M)
# I attempt to use the new class definition with the old instance:
M.A.f(old_a)

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

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

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

Ответы [ 2 ]

5 голосов
/ 06 февраля 2012

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

old_a.__class__=M.A
old_a.f()

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

РЕДАКТИРОВАТЬ: Как указывает jsbueno: Методы __init__ или __new__ не вызываются в точке изменения __class__.Далее, новый __del__ будет вызываться при уничтожении.

0 голосов
/ 06 февраля 2012

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

Шаг 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 не тронут.Действительно, оно может быть неизменным.

...