【问题标题】:Python: Overriding (monkey patching) ClassPython:覆盖(猴子补丁)类
【发布时间】:2017-10-05 21:21:08
【问题描述】:

我想在运行时覆盖(修补)一个类。在我的情况下,我使用 gui2py 并希望覆盖它的一些功能以支持 MenuItems 中的图像,但不更改最终程序的代码。

即我有

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()

然后就可以了

Download This 用于工作演示

【问题讨论】:

  • 我想问题是你正在修补__init__,只需将函数设置为类属性。你应该在这样做之前把它变成instance method
  • __init__ 以某种方式按预期工作,是类属性 image 进行了更改。如果直接在源码中修改或者覆盖
  • 那你的错误信息是什么?

标签: python class overriding monkeypatching class-variables


【解决方案1】:

好的,经过数小时的研究,似乎这是将属性添加到类的正确方法:

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

# and then:        
gui.MenuItem = _MenuItem

现在可以正常使用了

【讨论】:

  • gui.MenuItem.image = ... 没有任何问题(除非MenuItems 元类定义了__setattr__ 并以某种方式干扰)。我想您的解决方案在大多数情况下也适用,但错误消息将有助于找出前一种方法不起作用的原因。请注意,如果gui.MenuItem 具有属性image,它仍然具有相同的属性。在__mro__ 中,它只是新的image,它首先解析_MenuItem 的实例。另请注意,如果对象在补丁之前存储了该引用,则任何类型检查(如 type(_MenuItem()) == OriginalMenuItem)都会失败。
猜你喜欢
  • 2011-04-15
  • 2012-07-26
  • 2012-08-10
  • 2012-12-18
  • 1970-01-01
  • 1970-01-01
  • 2012-08-19
  • 2016-09-01
  • 2012-09-16
相关资源
最近更新 更多