Как перезагрузить код метода класса объекта в Python? - PullRequest
3 голосов
/ 12 января 2011

Я нахожу способ перезагрузить метод объекта класса во время выполнения , вот пример: сначала я определил класс A, который лежит в файле test.py.

class A:
    def __init_(self):
        pass
    def Message(self):
        print "1"

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

>>> from test import A
>>> a = A()
>>> a.Message()
1

Теперь я на лету проверяю test.py и меняю метод «Сообщение»:

class A:
    def __init_(self):
        pass
    def Message(self):
        print "2"

но когда я выполняю a.Message () в оболочке Python, результатом всегда будет «1», а не «2»

Как я пишу код для создания объекта «a.Message»выполнить обновленный код.

Большое спасибо!

Чу

Ответы [ 3 ]

4 голосов
/ 12 января 2011

Чтобы перевести ваш модуль в интерактивный интерпретатор, вы можете использовать

import test
reload(test)
from test import A

Но это не повлияет на уже существующий экземпляр A - он все равно будет старого типа A, следовательно, имея старый метод.Я думаю, что невозможно изменить существующие экземпляры, и при этом я не думаю, что это хорошая идея.

Кстати, я бы рекомендовал использовать IPython для тестирования кода.Он облегчает рекурсивную перезагрузку с использованием магии %reload и (что еще более полезно) магии %run для тестирования модулей.

1 голос
/ 04 марта 2014

Я просто потратил некоторое время, пытаясь решить эту проблему самостоятельно, и в результате получил немного отличающееся решение от других, предложенных здесь. Я поместил его в gist с большим количеством комментариев, но, как и в случае SO, я дам краткое объяснение здесь:

Вместо того, чтобы изменять отдельные экземпляры старой версии класса или копировать их в новые экземпляры нового класса, идея состоит в том, чтобы установить методы старого класса (то есть атрибуты самого класса, а не экземпляры класс), чтобы быть обновленными методами из нового класса. Он также заботится о связывании нескольких версий класса.

0 голосов
/ 05 апреля 2013

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

import sys
def update_class(instance):
  cls=instance.__class__
  modname=cls.__module__
  del sys.modules[modname]
  module=__import__(modname)
  instance.__class__=getattr(module,cls.__name__)

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

import sys

class ObjDebug(object):
  def __getattribute__(self,k):
    ga=object.__getattribute__
    sa=object.__setattr__
    cls=ga(self,'__class__')
    modname=cls.__module__ 
    mod=__import__(modname)
    del sys.modules[modname]
    reload(mod)
    sa(self,'__class__',getattr(mod,cls.__name__))
    return ga(self,k)

class A(ObjDebug):
   pass

a=A()

Если вы отредактируете код A, чтобы добавить метод, то вы можете использовать его, не создавая экземпляр снова.создавать неприятные ошибки, для которых некоторые символы становятся объектами None от одной строки к другой.(не понятно почему)

...