【问题标题】:Binding class methods to external functions将类方法绑定到外部函数
【发布时间】:2013-04-02 23:34:54
【问题描述】:

尝试将类方法绑定到函数时出现错误。为什么?

def foo():
    print "Hello world"

class something(object):
    bar = foo

test = something()
test.bar()

TypeError: foo() takes no arguments (1 given)

另外,如果我无法修改 foo,我可以在类定义中进行此调整吗?

【问题讨论】:

    标签: python oop methods


    【解决方案1】:

    一种简单的方法是将函数包装在 A 内的 staticmethod 中:

    class A():
        bar = staticmethod(foo)
    
    >>> test = A()
    >>> test.bar()
    Hello world
    

    【讨论】:

    • 我非常喜欢这个解决方案。我想这只有在我不需要从函数内部访问实例时才有效(但这是我更新中假设的一部分)
    【解决方案2】:

    python 中的类方法总是至少需要一个参数,通常称为self。这个例子取自official Python tutorial

    # Function defined outside the class
    def f1(self, x, y):
        return min(x, x+y)
    
    class C:
        f = f1
        def g(self):
            return 'hello world'
        h = g
    

    请注意,这两种方法,无论是在类外部还是内部定义,都将self 作为参数。

    编辑:如果你真的不能改变你的foo函数,那么你可以这样做:

    >>> def foo():
    ...     print "Hello World"
    ...
    >>> class something(object):
    ...     def bar(self): foo()
    ...
    >>> test = something()
    >>> test.bar()
    Hello World
    

    【讨论】:

    • 说我不能修改foo(或者我不想改变它的签名)。我可以从类定义中进行这种调整吗?
    • 太棒了。谢谢@srgerg。我喜欢 Python。
    • 查看@BrenBarn 了解解决“无法更改foo”问题的有趣方法
    • 是的,我更喜欢 BrenBarn 的解决方案。
    【解决方案3】:

    当您以这种方式调用类方法时,您将类实例作为第一个参数传递。 当您致电test.bar 时,实际上发生的事情更像bar(test)。您将参数传递给方法。

    【讨论】:

      【解决方案4】:

      类方法都有一个类实例的第一个参数。所以给你的函数添加一个参数,它就可以工作了。

      【讨论】:

        【解决方案5】:

        初始 def 创建一个名为 foo 的函数对象。由于它在任何类之外,它只是一个不带参数的函数。赋值bar = foo 只是将新名称test.bar 赋予同一个函数对象。然而,调用test.bar() 假定bar 是一个类方法,并将对象test 作为第一个参数传递给该方法(您通常会调用self)。您可以使用 something.bar() 将其作为静态方法调用,而不会出现错误。

        【讨论】:

          【解决方案6】:

          请记住,当 Python 类调用其中一个方法时,它会传入一个 self 参数。您需要在代码中考虑到这一点:

          def foo(self):
              print ("Hello world")
          
          class something(object):
              bar = foo
          
          test = something()
          test.bar()
          

          您可以在Python Documentation 中阅读有关课程的所有信息

          我能想到的不传递self 的最简单解决方法是:

          def foo():
              print ("Hello world")
          
          class something(object):
              bar = [foo] # contains pointer to static method
          
          test = something()
          test.bar[0]() # calls the static method
          

          【讨论】:

          • 谢谢。我已经更新了 OP 以澄清我正在寻找一种不需要修改 foo 而只需要修改类定义本身的方法。
          • @user815423426 已编辑,可能有更好的方法,但这个方法可行,我想您现在可以添加任意数量的不同功能。
          猜你喜欢
          • 2018-06-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-27
          • 2011-07-17
          • 2018-06-28
          • 1970-01-01
          • 1970-01-01
          • 2011-05-10
          相关资源
          最近更新 更多