在Python中,可以调用类A的实例方法并传入类B的实例吗?

6 投票
4 回答
2746 浏览
提问于 2025-04-15 11:13

为了重用一些已经存在的代码,这些代码是定义在另一个类的实例方法中,我试图做类似下面的事情:

class Foo(object):
  def __init__(self):
    self.name = "Foo"

  def hello(self):
    print "Hello, I am " + self.name + "."

class Bar(object):
  def __init__(self):
    self.name = "Bar"


bar = Bar()
Foo.hello(bar)

但是这样做会导致:

类型错误:未绑定的方法 hello() 必须用 Foo 类的实例作为第一个参数(而我却用的是 Bar 类的实例)

这样做有可能吗?


我应该更清楚地说明,我知道这样做不好。显然,真正的解决办法是稍微重构一下代码。我只是觉得应该有办法做到,结果发现确实有。

谢谢大家的评论。

4 个回答

2

这是个老问题,但Python已经发展了很多,值得提一下:

在Python 3中,不再有<unbound method C.x>这个概念,因为一个未绑定的方法其实就是<function __main__.C.x>

这可能意味着原问题中的代码其实并没有那么离谱。毕竟,Python一直以来都是强调鸭子类型的,不是吗?

参考资料:

Python 2中的替代解决方案

请注意,还有一个替代方案可以解决这个“探索性”的问题(见Python:绑定一个未绑定的方法?):

In [6]: a = A.a.im_func.__get__(B(), B)

In [7]: a
Out[7]: <bound method B.a of <__main__.B instance at 0x7f37d81a1ea8>>

In [8]: a(2)
2

参考:

一些ipython代码示例

Python 2

In [1]: class A():
    def a(self, a=0):
        print a
   ...:

In [2]: A.a
Out[2]: <unbound method A.a>

In [3]: A.a.im_func
Out[3]: <function __main__.a>

In [4]: A.a(B())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-7694121f3429> in <module>()
----> 1 A.a(B())

TypeError: unbound method a() must be called with A instance as first argument (got B instance instead)

Python 3

In [2]: class A():
    def a(self, a=0):
        print(a)
   ...:

In [3]: def a():
   ...:     pass
   ...:

In [4]: class B():
   ...:     pass

In [5]: A.a(B())
0

In [6]: A.a
Out[6]: <function __main__.A.a>
5

这个问题发生是因为Python把类中的函数包装成一种叫“未绑定方法”的东西,这种方法会进行类型检查。关于这个决策的详细信息可以在这里找到。

需要注意的是,这种类型检查在Python 3中已经被取消了(可以在那篇文章的最后看到说明),所以你的做法在Python 3中是可以正常工作的。

9

看起来这个可以用:

Foo.hello.im_func(bar)

你好,我是Bar。

我想我需要更仔细地阅读一下这个文档...

撰写回答