关于oop:在Python中,你可以调用类A的实例方法,但是传入一个B类的实例吗?

In Python, can you call an instance method of class A, but pass in an instance of class B?

为了重用一些定义为不同类的实例方法的现有代码,我打算执行如下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)

但结果是:

TypeError: unbound method hello() must be called with Foo instance as first argument (got Bar instance instead)

这样的事情有可能吗?

我应该清楚我知道这是个坏主意。显然,真正的解决方案是重构。我只是想一定有办法,结果证明是有办法的。

谢谢你的评论。


看起来这是可行的:

1
Foo.hello.im_func(bar)

Hello, I am Bar.

我想我需要更努力地阅读…


发生这种情况是因为python将类函数包装为执行此类型检查的"未绑定方法"。这里有一些有关决定的描述。

注意,这种类型检查实际上已经在python 3中被删除了(参见文章末尾的注释),因此您的方法可以在这里工作。


这是一个古老的问题,但是python已经进化了,看起来值得指出:

对于python 3,没有更多的,因为一个未绑定的方法只是一个

这可能意味着不应该考虑原始问题中的代码。无论如何,python一直都是关于鸭子打字的,不是吗?!

参考文献:

  • guido建议从python中删除未绑定的方法
  • Python3版本的新增功能
  • 获取python 3中未绑定方法对象的定义类

PY2中的替代溶液

请注意,对于"探索性"问题,还有另一种解决方案(请参见python:bind an unbound method?):

1
2
3
4
5
6
7
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代码示例Python2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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)

Python3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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>


前一段时间,我对Perlmounds上Perl的相同"特性"感到好奇,大家普遍认为,当它工作时(就像在Python中一样),您不应该这样做。