Python 中的代表

问题描述 投票:0回答:3

我实现了这个简短的示例来尝试演示一个简单的委托模式。我的问题是。这看起来我已经理解了委托吗?

class Handler:
    def __init__(self, parent = None):
        self.parent = parent
    def Handle(self, event):
        handler = 'Handle_' +event
        if hasattr(self, handler):
            func = getattr(self, handler)
            func()
        elif self.parent:
            self.parent.Handle(event)

class Geo():
    def __init__(self, h):
        self.handler = h

    def Handle(self, event):
        func = getattr(self.handler, 'Handle')
        func(event)

class Steve():
    def __init__(self, h):
        self.handler = h

    def Handle(self, event):
        func = getattr(self.handler, 'Handle')
        func(event)

class Andy():
    def Handle(self, event):
        print 'Andy is handling %s' %(event)

if __name__ == '__main__':        
    a = Andy()
    s = Steve(a)
    g = Geo(s)
    g.Handle('lab on fire')
python design-patterns delegates
3个回答
17
投票

一个 Python 技巧:你不需要说:

func = getattr(self.handler, 'Handle')
func(event)

就说:

self.handler.Handle(event)

我不确定你正在使用 Handler 类做什么,它没有在你的示例中使用。

在 Python 中,具有大写名称的方法非常非常不寻常,通常是移植某些具有此类名称的现有 API 的结果。


10
投票

这是基本概念,是的 - 将一些传入请求传递给另一个对象来处理。


0
投票

也想知道同样的事情,Python 似乎不支持委托作为内置功能,并且在这种类型的底层内容上使用大量 opensrc 库进行扩展有时会带来严重的质量风险,因为您添加了依赖项对于或多或少关键领域的第三方来说,这当然完全取决于软件包以及它是否正在积极开发,但仍然如此。

我很久以前就发现通过 C# 了解更多关于委托的知识很有帮助,有很好的文档可以很好地解释它们。

查看评论,我读到 Ashbay 建议您使用 hasattr() 确保类中存在函数。现在,由于您正在使用多个类的委托,而不是函数委托(请参阅 C#,有很好的解释),那么为什么不在您希望通过委托使用的类中使用这两个东西呢:

您可以通过为您的真实类“作为契约”定义一个接口来删除函数调用(节省一次进程运行)。该契约确保契约中的所有内容始终在您的类层次结构链中实现,以履行约定的契约。

接口通常使用内置的 abc python 包(抽象基类)来完成:

看看为什么用作 abc 包(抽象类)来定义接口类有点笨拙:https://interface.readthedocs.io/en/latest/abc.html

通过这个项目,你可以获得这样的常规功能(为什么它们甚至缺失,在强大的 OoP 中非常重要!)。不幸的是,它们还没有内置,但无论如何它在这里:https://pypi.org/project/python-interface/#description

  • 您可以使类更加通用,继承父类,通常使用接口,您可以将它们承包给父类,然后标记抽象并“传递”,以防您希望在子类中实现它们。只有当实现确实发生变化/需要有差异时,您才应该这样做,否则只需使其对所有人通用(如果您继承了很多,则可以节省大量编码时间和代码重复 --> 因此,使用具有抽象方法的抽象基类是这是一个灾难性的模式)。

  • 不确定 python 是否提供了像 C# 中那样进行虚拟重写的好方法,在 C# 中,您可以使用“两者最佳”,这样您就可以仅在真正需要时进行重写,然后默认使用该父类实现。最有可能的是它可以完成,但是 python 有点“叛逆”,因为它做的很多事情都略有不同:)但是,看起来上面链接中的接口 python 包至少对这些有一些支持。

此外,还发现了这个博客,其中讨论了提供多种选项的主题: https://michaelcho.me/article/method-delegation-in-python

选项3中的委托人可能指的是这个库: https://pypi.org/project/ObjectDelegator/

个人观点是,如果您能够并且有时间更准确地设计您的类级别架构,那么在大多数情况下您根本不需要委托。就尝试使代码在循环结构中更加通用和可利用而言,委托应该更像是您的“最后手段”。不管怎样,有时(但很少)你确实需要它们。

ps。我的第一个堆栈溢出评论,如果我在某些外观等样式问题上未能正确,我深表歉意:)

© www.soinside.com 2019 - 2024. All rights reserved.