Python方法作为参数

7

我知道在Python中一切都是“对象”,这意味着它可以作为参数传递给方法。但是我想了解这究竟是如何工作的。所以我尝试了以下例子:

class A:

    def __init__(self):
        self.value = 'a'

    def my_method(self)
        print self.value

class B:

   def __init__(self):
       self.values = 'b'

   def my_method(self, method):
       method()

a = A()
b = B()
b.my_method(a.my_method)

首先,这篇文章是为了了解事物的运作方式而写的。我知道应该检查my_method的参数是否可调用。现在我的问题是:

这个方法是如何传递的?我的意思是,我收到的输出是“a”,所以我猜想当一个对象方法作为参数被传递时,实际的对象也会被传递?在这种情况下,当我传递a.my_method时,实例a也会被传递?


2
如果你正在使用Python 2,请使用class A(object):而不是class A:来获取“新式类”,这通常更好,也是你应该使用的。 - Chris Morgan
4个回答

8
当您访问 a.my_method 时,Python会看到它是类的属性,并且 A.my_method 有一个方法 __get__(),所以它调用 A.my_method.__get__(a) 方法,该方法创建一个新对象(即“绑定方法”),其中包含对 A.my_methoda 本身的引用。当您调用绑定方法时,它会将调用传递回基础方法。
每次调用任何方法时都会发生这种情况,无论您是直接调用还是像您的代码一样延迟实际调用。您可以在http://docs.python.org/reference/datamodel.html#descriptors中找到更多关于描述符协议的描述。

感谢您的输入。在熟悉Python之前,它可能会让人感到棘手:D - Bogdan

4
这里的方法是如何传递的呢?
很容易回答:在Python中,一切都是对象 :) 函数/方法也是特定的函数对象,可以作为参数传递。
在这种情况下,当我传递a.my_method时,实例a也被传递了吗?
是的,在这种情况下,实例a也被传递了,尽管它嵌入在函数对象中,无法检索。相反,您可以传递函数本身并向其提供实例。请考虑以下示例:
b = B()
func = A.my_method # Attention, UPPERCASE A
func(b)

这将使用 B 的实例调用 A 类的方法 my_method

严格来说,A.my_method并不是函数本身,而是一个未绑定方法对象。a.my_method是一个绑定方法对象。如果你真的需要的话(使用inspect模块),你可以从a.my_method中检索出a实例和原始函数,但我不认为在这里有理由这样做。 - Jürgen Strobel
我尝试了你的建议,但唯一有效的方法是将A.my_method作为一个带有obj参数的静态方法。否则它需要一个A类的实例。 - Bogdan

1

在Python中,函数是“一等对象”。这意味着函数与列表或整数一样都是对象。当您定义一个函数时,实际上是将函数对象绑定到您在def中使用的名称。

函数可以绑定到其他名称,也可以作为参数传递给函数(或存储在列表中等等)。

来源:http://mail.python.org/pipermail/tutor/2005-October/042616.html


1

a.my_method 返回的不是你在 class A 中定义的函数(你可以通过 A.my_method 获取它),而是一个称为“绑定方法”的对象,其中包含原始函数(或 Python 2 中的“未绑定方法”,如果我没记错的话)和从中检索它的对象(即 self 参数)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接