Python: замена функции в классе модуля - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь заменить функцию, определенную в классе, чтобы изменить ее функцию (как во внутренней работе) без изменения фактического кода.Я никогда не делал этого раньше, следовательно, возникли некоторые проблемы при замене.Изменение кода даст мне доступ к пакету в моей библиотеке python, что не является чем-то особенным.

Например, если модуль назывался testMOD

class testMOD(object):
      def testFunc(self, variable):
          var = variable
          self.something = var + 12

Тогда я импортировал бы testMOD,определите класс (mytest = testMOD ()) и получите доступ к определенной функции в классе testFunc и измените ее на уже определенную функцию.

Например,

from somemodule import testMOD
mytest = testMOD()

def alternativeFunc(self, variable):
    var = variable
    self.something = var + 1.2

#problem here
mytest.testFunc = alternativeFunc

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

Что я хочу сделать, так это сделать заменяющую функцию точно такой же, как заменяемая, но с дополнительным кодом или некоторыми незначительными изменениями.Тем не менее, «я» в значительной степени не работает, как должно быть в классе.Есть ли способ правильно реализовать определенную функцию, чтобы заменить функцию импортированного класса?

Ответы [ 3 ]

0 голосов
/ 30 мая 2018

Вы можете обезьяна патч этот метод следующим образом:

class TestMOD(object):

    def testFunc(self, variable):
        var = variable
        self.something = var + 12
        print(f'original {self.something}')


def alternativeFunc(self, variable):
    var = variable
    self.something = var + 1.2
    print(f'alternative {self.something}')


if __name__ == '__main__':

    test_original = TestMOD()
    test_original.testFunc(12)

    TestMOD.testFunc = alternativeFunc

    test_alternate = TestMOD()
    test_alternate.testFunc(12)

вывод:

original 24
alternative 13.2
0 голосов
/ 30 мая 2018

Я предлагаю 4 решения, от худшего к лучшему (ИМХО), но, конечно, это также зависит от ваших конкретных ограничений:

  1. Замените метод экземпляра (1): Iиспользуйте тот факт, что функции являются дескрипторами в Python, так что я могу использовать метод __get__ для AlternativeFunc, чтобы получить его как метод экземпляра mytest и перезаписать метод testFunc экземпляра mytest (без перезаписи метода класса):

    class testMOD(object):
        def testFunc(self, variable):
            var = variable
            self.something = var + 12
            print('Original:', self.something)
    
    def alternativeFunc1(self, variable):
        var = variable
        self.something = var + 1.2
        print('Alternative1:', self.something)
    
    mytest1 = testMOD()
    mytest1.testFunc(10)   # Original: 22
    
    mytest1.testFunc = alternativeFunc1.__get__(mytest1, testMOD)
    mytest1.testFunc(10)   # Alternative1: 11.2
    mytestX = testMOD()
    mytestX.testFunc(10)   # Original: 22
    
  2. Заменить метод экземпляра (2): На этот раз я использую types.MethodType, который немного более читабелен, чем первое решение:

    import types
    
    class testMOD(object):
        def testFunc(self, variable):
            var = variable
            self.something = var + 12
            print('Original:', self.something)
    
    def alternativeFunc1(self, variable):
        var = variable
        self.something = var + 1.2
        print('Alternative1:', self.something)
    
    mytest1 = testMOD()
    mytest1.testFunc(10)   # Original: 22
    
    funcType = types.MethodType
    mytest1.testFunc = funcType(alternativeFunc1, mytest1)
    mytest1.testFunc(10)   # Alternative1: 11.2
    mytestX = testMOD()
    mytestX.testFunc(10)   # Original: 22
    
  3. Выполните исправление обезьяны метода класса.В отличие от первого метода, он изменяет поведение любого экземпляра класса:

    class testMOD(object):
        def testFunc(self, variable):
            var = variable
            self.something = var + 12
            print('Original:', self.something)
    
    def alternativeFunc2(self, variable):
        var = variable
        self.something = var + 1.2
        print('Alternative2:', self.something)
    
    mytest2 = testMOD()
    mytest2.testFunc(10)   # Original: 22
    
    testMOD.testFunc = alternativeFunc2
    mytest2.testFunc(10)   # Alternative2: 11.2
    mytestX = testMOD()
    mytestX.testFunc(10)   # Alternative2: 11.2
    
  4. Создайте класс, унаследованный от testMOD, чтобы переопределить метод:

    class testMODNew(testMOD):
         def testFunc(self, variable):
             var = variable
             self.something = var + 1.2
             print('Alternative3:', self.something)
    
    mytest3 = testMODNew()
    mytest3.testFunc(10) # Alternative3: 11.2
    
0 голосов
/ 30 мая 2018

проверьте наследование классов в python, чтобы создать свой собственный класс:

from somemodule import TestMOD

class YourCustomClass(TestMOD):

    # change the function
    def test_func(self, variable):
        #
        #

your_class = YourCustomClass()
your_class.test_func(x)
...