2017-05-08 8 views
0

実行時にクラスをオーバーライド(パッチ適用)したいと思います。私の場合、私はgui2pyを使い、MenuItemsの画像をサポートする機能をいくつかオーバーライドしたいが、最終的なプログラムのコードは変更しない。Python:オーバーライド(monkey patching)クラス

つまり私は、これは動作しません

overrides.py

import gui,wx 

# this is the tricky line  
gui.MenuItem.image = gui.component.InitSpec() 

def menu__init__(self, parent, *args, **kwargs): 
    gui.menu.wx_DummyWindow.__init__(self, parent, *args, **kwargs) 
    wx.MenuItem.__init__(self, parentMenu=parent,id=kwargs['id'],text=kwargs['label'],kind=kwargs['style']) 

    if self.GetKind() == wx.ITEM_SEPARATOR: 
     self.parent.AppendSeparator()  
    else: 
     self.SetHelp(kwargs['help']) 
     # The next is added code 
     img = kwargs.get("image") 
     if img: 
      self.SetBitmap(wx.Bitmap(img)) 

     self.parent.AppendItem(self) 

gui.menu.wx_MenuItem.__init__ = menu__init__ 

program.py

from overrides import * 

with gui.Window(name='win', ): 

    with gui.MenuBar(name='menu',): 
     with gui.Menu(label=u'File', name='file',): 
      gui.MenuItem(label=u'Quit', name='quit', image='quit.png') 

gui.main_loop() 

を持っています。

私はGUI/menu.pyに直接

class MenuItem(Component): 
    #add this line 
    image = InitSpec() 

を変更した場合しかし、それは[OK]を働いデモ

+0

私は、関数をクラス属性として設定するだけで、 '__init__'にパッチを当てていると思います。その前に[インスタンスメソッド](https://docs.python.org/2/library/types.html#types.MethodType)に変換する必要があります。 –

+0

どういうわけか '__init__'は期待通りに機能しますが、変更を行うのはクラスのプロパティ_image_です。ソースで直接変更または上書きされた場合 – Magen

+0

エラーメッセージはどうなりますか? –

答えて

0

ため

Download Thisを働き、これがあるように、研究の時間の後に思えますクラスに属性を追加する正しい方法:

class _MenuItem(gui.MenuItem): 
    image = gui.component.InitSpec() 

# and then:   
gui.MenuItem = _MenuItem 

これでうまくいきます。

+0

'gui.MenuItem.image = ...'に何も問題はありません( 'MenuItem'のメタクラスが' __setattr__'を定義して何らかの方法で干渉しない限り)。私はあなたのソリューションがほとんどの場合でもうまくいくと思いますが、エラーメッセージは、前者のアプローチがうまくいかなかった理由を理解するのに役立ちます。 'gui.MenuItem'が属性' image'を持っていれば、それと同じ属性を持っていることに注意してください。 '__mro__'では' _MenuItem'のインスタンスを最初に解決する新しい 'イメージ'です。また、 'type(_MenuItem())== OriginalMenuItem'のような型チェックは、パッチの前にオブジェクトがその参照を格納していれば失敗します。 –