返回介绍

Call表达式:__call__

发布于 2024-01-29 22:24:15 字数 2494 浏览 0 评论 0 收藏 0

当调用实例时,使用__call__方法。不,这不是循环定义:如果定义了,Python就会为实例应用函数调用表达式运行__call__方法。这样可以让类实例的外观和用法类似于函数。

更正式地说,我们在第18章介绍的所有参数传递方式,__call__方法都支持——传递给实例的任何内容都会传递给该方法,包括通常隐式的实例参数。例如,方法定义:

都匹配如下所有的实例调用:

直接的效果是,带有一个__call__的类和实例,支持与常规函数和方法完全相同的参数语法和语义。

像这样的拦截调用表达式允许类实例模拟类似函数的外观,但是,也在调用中保持了状态信息以供使用(我们在本书第17章中介绍作用域的时候看到过一个类似的示例,但是,在这里,你应该对运算符重载更熟悉):

在这个示例中,__call__乍一看可能有点奇怪。一个简单的方法可以提供类似的功能:

然而,当需要为函数的API编写接口时,__call__就变得很有用:这可以编写遵循所需要的函数来调用接口对象,同时又能保留状态信息。事实上,这可能是除了__init__构造函数以及__str__和__repr__显示格式方法外,第三个最常用的运算符重载方法了。

函数接口和回调代码

作为例子,tkinter GUI工具箱(在Python 2.6中是Tkinter)可以把函数注册成事件处理器(也就是回调函数callback)。当事件发生时,tkinter会调用已注册的对象。如果想让事件处理器保存事件之间的状态,可以注册类的绑定方法(bound method)或者遵循所需接口的实例(使用__call__)。在这一节的代码中,第二个例子中的x.comp和第一个例子中的x都可以用这种方式作为类似于函数的对象进行传递。

下一章会再介绍绑定方法,这里仅举一个假设的__call__例子,应用于GUI领域。下列类定义了一个对象,支持函数调用接口,但是也有状态信息,可记住稍后按下按钮后应该变成什么颜色。

现在,在GUI环境中,即使这个GUI期待的事件处理器是无参数的简单函数,我们还是可以为按钮把这个类的实例注册成事件处理器。

当这个按钮按下时,会把实例对象当成简单的函数来调用,就像下面的调用一样。不过,因它把状态保留成实例的属性,所以知道应该做什么。

实际上,这可能是Python语言中保留状态信息的最好方式,比之前针对函数所讨论的技术更好(全局变量、嵌套函数作用域引用以及默认可变参数等)。利用OOP,状态的记忆是明确地使用属性赋值运算而实现的。

在继续之前,Python程序员偶尔还会用两种其他方式,把信息和回调函数联系起来。其中一个选项是使用lambda函数的默认参数:

另一种是使用类的绑定方法:这种对象记住了self实例以及所引用的函数,使其可以在稍后通过简单的函数调用而不需要实例来实现。

当按钮按下时,就好像是GUI这么做的,启用changeColor方法来处理对象的状态信息:

这种技巧较为简单,但是比起__call__重载调用而言就不通用了;同样,有关绑定方法可参考下一章的内容。

在第31章你会看到另一个__call__例子,我们会通过它来实现所谓的函数装饰器的概念:它是可调用对象,在嵌入的函数上多加一层逻辑。因为__call__可让我们把状态信息附加在可调用对象上,所以自然而然地成为了被一个函数记住并调用了另一函数的实现技术。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文