gpt4 book ai didi

python - 实现代理对象

转载 作者:太空宇宙 更新时间:2023-11-04 06:10:13 24 4
gpt4 key购买 nike

我的问题

我在 Python 中使用 wxWidgets 库(通过 wxPython 包装器)。我正在尝试实现一个类 PaddedStaticText,它的行为与 WX StaticText 类相同,但每一侧都有一个用户可配置的填充。理想情况下,PaddedStaticText 将是 StaticText 的直接替代品。那种尖叫“子类化”,对吧?不幸的是,我认为如果我要子类化 StaticText,我基本上必须重新实现它的所有绘图例程,而我没有 WX 专业知识来做到这一点。

解决方案一

我想出的解决方案是实现一个具有 StaticText 属性的类,该属性将放置在几个 Sizers 中以影响填充:

class PaddedStaticText(wx.Window):
def __init__(self, parent, label='', padding=(0, 0, 0, 0), **kwargs):
wx.Window.__init__(self, parent)

self.text = wx.StaticText(self, label=label, **kwargs)

inner_sizer = wx.BoxSizer(wx.VERTICAL)

inner_sizer.Add((0, padding[0]))
inner_sizer.Add(self.text, proportion=1, flag=wx.EXPAND)
inner_sizer.Add((0, padding[2]))

outer_sizer = wx.BoxSizer(wx.HORIZONTAL)

outer_sizer.Add((padding[3], 0))
outer_sizer.Add(inner_sizer, proportion=1, flag=wx.EXPAND)
outer_sizer.Add((padding[1], 0))

self.SetSizer(outer_sizer)

这个类继承自 wx.Window,所以它可以用在许多我可以使用 StaticText 的相同上下文中——例如,将它添加到 Sizer。但是,由于 PaddedStaticText 实际上不是 StaticText,我不能只对其中一个实例调用 SetFont()。我必须制作自己的代理方法:

    def SetFont(self, *args, **kwargs):
self.text.SetFont(*args, **kwargs)

当然,我必须为我希望可用的每个 StaticText 方法编写这样一个 stub 。这种方法有效,但一点也不优雅。我想在 Python 中一定有更好的方法来做这样的事情。

方案二

基于 this SO answer我写了这个简单的代理类:

class Proxy(object):
def __init__(self, underlying_object):
self._underlying_object = underlying_object

def __getattribute__(self, name):
obj = object.__getattribute__(self, '_underlying_object')
return object.__getattribute__(obj, name)

然后我可以将 PaddedStaticText 表示为 Proxy 的子类,并将 underlying_object 设置为 StaticText 实例。不幸的是,当我尝试将新的 PaddedStaticText 实例添加到 Sizer 时,WX 犹豫不决。因为它是 C++ 库的包装器,我猜 WX 并不真正尊重 Python 的鸭子类型:即使 PaddedStaticText 可以在调用 StaticText 方法时做出适当的响应,wxPython 所关心的只是它继承自 Proxy 而不是来自 wx.Window。

从那里开始,我简单地尝试了让 PaddedStaticText 从 Proxy 和 wx.Window 继承,但这没有用(无论如何它是一个继承菱形的例子)。如何以 Just Works 的方式实现我的 PaddedStaticText 类?对于我的解决方案想法或解决问题的完全不同的建议,我将不胜感激。

最佳答案

我会做的是:

class PaddedStaticText(wx.Window):

def __init__(...):
self.text = ...
...

def __getattr__(self, name):
'''delegate missing attributes to text'''
return getattr(self.text, name)

它通过故障转移扩展了您的基本继承方法(__getattr__ 仅在没有其他工作时才被调用)到委派。

这使事情接近 wxwindows 所期望的,并减少了魔法的数量,但仍然允许您访问诸如 SetFont 之类的东西。

或者,如果您要使用 .text(而不是 .__text),那么您可以使用它:

foo = PaddedStaticText(...)
foo.text.SetFont(...)

但您将无法替换现有的 StaticText 实例。

[edit] 已经晚了,所以我明天可能会改进这个,但是如果您需要使用 __getattribute__ 那么我建议您明确说明您想要的方法。它更多的是打字,但根据我的经验,python 中的全自动代理通常最终会以令人讨厌的方式让你大吃一惊。所以像这样:

def __getattribute__(self, name):
if name in ('SetFont', ...):
return getattr(self.text, name)
else:
return super(...).__getattribute__(self, name)

或(可能更快,但每个实例消耗更多内存):

def __init__(...):
self.text = ...
for name in ('SetFont', ...):
setattr(self, name, getattr(self.text, name))

关于python - 实现代理对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19278411/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com