【问题标题】:In Python, can you call an instance method of class A, but pass in an instance of class B?在 Python 中,可以调用 A 类的实例方法,但传入 B 类的实例吗?
【发布时间】:2010-10-21 12:34:56
【问题描述】:

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

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 实例作为第一个参数(改为获取 Bar 实例)

这样的事情可能吗?


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

感谢cmets。

【问题讨论】:

  • 看起来 Python 给了你答案。无论如何,这是重用现有代码的错误方法。
  • 为什么不想分解出通用功能并从 Foo 和 Bar 的实例方法中调用它?
  • 是的,这显然是错误的做法。由于 Python 的动态特性,我只是假设它可以完成,当它没有按我预期的那样工作时有点惊讶。
  • -1:这种方法太不合理了,让我胆战心惊。如果可以做到,应该禁止故意误导。
  • 请记住,Python 是强类型的,并且起源于 centre for mathematics。毫不奇怪,它会发出 TypeError 信号!

标签: python oop coding-style


【解决方案1】:

看起来这样可行:

Foo.hello.im_func(bar)

你好,我是巴尔。

我想我需要更努力地阅读this...

【讨论】:

  • 是的,但这是你永远不应该做的事情(除了了解它是如何工作的)。
  • 有趣的发现。但同意将其用于此处提出的问题是不合适的。
  • 我不打算实际使用它。这只是一个“这是如何工作的”问题。我将在原始问题中添加注释。
  • 使用它可能是合法的。这应该是这个问题的公认答案。
【解决方案2】:

这是因为 python 将类函数包装为执行此类型检查的“未绑定方法”。对此here 中涉及的决策有一些描述。

请注意,这种类型检查实际上已在 python 3 中删除(请参阅该文章末尾的注释),因此您的方法将在那里有效。

【讨论】:

    【解决方案3】:

    这是一个老问题,但 Python 已经发展,看起来值得指出:

    在 Python 3 中不再有 <unbound method C.x>,因为未绑定的方法只是 <function __main__.C.x>

    这可能意味着不应将原始问题中的代码视为 /that/ off。无论如何,Python 一直都是关于鸭子类型的,不是吗?!

    参考:

    Py2 中的替代解决方案

    请注意,对于“探索性”问题还有一个替代解决方案(请参阅Python: Bind an Unbound Method?):

    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 代码示例

    蟒蛇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)
    

    蟒蛇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>
    

    【讨论】:

      【解决方案4】:

      不久前,我想知道 PerlMonks 上的 Perl 中是否有相同的“功能”,general consensus 是虽然它可以工作(就像它在 Python 中一样),但你不应该那样做。

      【讨论】:

        猜你喜欢
        • 2022-12-18
        • 2019-06-26
        • 2015-04-27
        • 2015-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多