2014-01-10 29 views
1

我想學習python猴子修補程序。我有一個簡單的例子,我試圖只修補一個實例而不是類本身。Python猴子修補對象不按預期方式工作

我的代碼:

# add.py 
import types 


class Math(object): 
    def __init__(self): 
     self.name = '' 

    def add(self, x, y, name): 
     self.name = name 
     print 'calling from ', self.name 
     return x + y 

    def monkey_patch(self): 
     add = self.add 

     def squared_sum(x, y): 
      return x**2 + y**2 
     add = types.MethodType(squared_sum, self) 


if __name__ == '__main__': 
    math = Math() 
    print math.add(3, 4, 'before monkey_patching') 
    math.monkey_patch() 
    print math.add(3, 4, 'after monkey_patching') 

預期輸出:

calling from before monkey_patching 
7 
calling from after monkey_patching 
25 

生成的輸出:

calling from before monkey_patching 
7 
calling from after monkey_patching 
7 

可有人POIN弄清楚我出錯的地方。另外,當我從不同的文件進行添加時,我該如何修改添加方法,即當我從不同文件中的add.py中導入Math類時,如何爲其添加方法的猴子修補程序。

回答

4

您的代碼不會做你認爲它的作用:

def monkey_patch(self): 
    add = self.add # add now points to self.add 
    def squared_sum(x, y): 
     return x**2 + y**2 
    add = types.MethodType(squared_sum, self) # add now points to squared_sum 
# method ends, add and squared_sum are abandoned 

,這實際上並不變化self.add。此外,squared_sum不參與selfname自變量,與add不同,並且不具有add所做的print。爲了全面完成這項工作,做到:

def monkey_patch(self): 
    def squared_sum(self, x, y, name): 
     self.name = name 
     print 'calling from ', self.name 
     return x**2 + y**2 
    self.add = types.MethodType(squared_sum, self) 

修補的類定義之外:

math = Math() 

def func(self, x, y, name): 
    return x ** y 

math.add = types.MethodType(func, math) 
+0

運行完美!有疑問。 self.add = types.MethodType(squared_sum,self)顯示在__init__警告外定義的實例屬性。現在我該如何將self.add移動到構造函數中? – Shankar

+0

你使用PyCharm還是什麼?當然,你正在「在__init__之外定義」,這就是你正在做的事情的整點。你可以忽略這個警告。確切地說, – jonrsharpe

+0

!我正在使用PyCharm!非常感謝! – Shankar