在Python中,可以调用类A的实例方法并传入类B的实例吗?
为了重用一些已经存在的代码,这些代码是定义在另一个类的实例方法中,我试图做类似下面的事情:
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