Динамическая загрузка метода экземпляра во время создания объекта - PullRequest
0 голосов
/ 14 сентября 2011

Я хочу иметь возможность динамически загружать методы экземпляра во время создания объекта. Согласно моей схеме поведение по умолчанию закодировано в базовом классе. Однако если определенные условия выполняются во время создания объекта, я динамически измените это поведение с другим фрагментом кода. Вот как Я делаю это:

Поведение по умолчанию закодировано в first.py:

class First(object):
    def __init__(self, p):
        p = str(p)
        #The decision whether or not to perform default action is done
        #in the following try/except block. In reality this block 
        #is more complicated
        #and more checks are performed in order to assure proper work
        try: 
            strImport = "__import__('module%s')"%p
            e = eval(strImport, {}, {})
            if not hasattr(e, p):
                raise ImportError()
        except ImportError:
            e = None #default behaviour
        if e is not None:
            self.act = getattr(e, p)(p).act #special behaviour
        self.p = p

    def act(self):
        print 'Default behaviour'


import cPickle as pickle



if __name__ == '__main__':
    print 'first'
    first = First('f')
    first.act()
    pickle.dump(first, open('first.dump', 'w'))

    print 'third'
    third = First('Third')
    third.act()
    pickle.dump(third, open('third.dump', 'w'))

В приведенном выше коде и first, и third выполняют действия по умолчанию. Я могу изменить поведение third путем добавления файла moduleThird.py следующим образом:

from temp import First
class Third(First):
    def __init__(self, p):
        p = 'Third *** %p'
        print 'third init'
        super(self.__class__, self).__init__(p)


    def act(self):
        super(self.__class__, self).act()
        print 'Third acted'

После добавления этого файла third меняет свое поведение. Однако я не не удалось засечь получившийся объект из-за следующей ошибки:

Traceback (most recent call last):
  File "C:\temp\temp.py", line 35, in <module>
    pickle.dump(fff, open('fff.dump', 'w'))
  File "C:\Python26\lib\copy_reg.py", line 70, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle instancemethod objects

Понятно, что метод динамической загрузки Third.act вызывает проблемы с рассолом. Как мне изменить свой подход, чтобы получить выбираемые объекты (и более элегантный код тоже)?

Есть ли лучший способ достичь моей цели?

1 Ответ

1 голос
/ 14 сентября 2011

Если вы измените свой код следующим образом, он должен работать:

class First(object):
    def __init__(self, p):
        p = str(p)
        #The decision whether or not to perform default action is done
        #in the following try/except block. In reality this block 
        #is more complicated
        #and more checks are performed in order to assure proper work
        try: 
            strImport = "__import__('module%s')"%p
            print strImport
            e = eval(strImport, {}, {})
            if not hasattr(e, p):
                raise ImportError()

            self.override_obj = getattr(e, p)(p)
        except ImportError:
            e = None #default behaviour
            self.override_obj = None

        self.p = p

    def act(self):
        if self.override_obj:
            return self.override_obj.act()
        else:
            print 'Default behaviour'
...