在Python中编写接受回调的类?

10 投票
6 回答
25183 浏览
提问于 2025-04-15 15:04

我需要写一个类,让它的子类可以设置一个属性,这个属性的名字是一个函数名。这个函数必须能从这个类的实例中调用。

举个例子,我想写一个水果类(Fruit),子类可以传入一个欢迎信息。这个水果类必须有一个可以设置的属性,叫做 print_callback。

class Fruit(object):
    print_callback = None

    def __init__(self, *args, **kwargs):
        super(Fruit, self).__init__(*args, **kwargs)
        self.print_callback("Message from Fruit: ")

我需要提供一个接口,让下面这段代码可以使用(为了说明,这段代码不能改动,假设它是第三方代码):

def apple_print(f):
    print "%sI am an Apple!" % f

class Apple(Fruit):
    print_callback = apple_print

如果我运行:

mac = Apple()

我希望得到:

来自水果的信息:我是一颗苹果!

但我得到的是:

类型错误:apple_print() 需要 1 个参数(给了 2 个)

我觉得这是因为 self 被当作第一个参数传进去了。

那么我该怎么写这个水果类呢?谢谢!

6 个回答

3

更新:根据abourget的建议,使用了staticmethod

试试这个:

def __init__(self, *args, **kwargs):
    super(Fruit, self).__init__(*args, **kwargs)

    # Wrap function back into a proper static method
    self.print_callback = staticmethod(self.print_callback)

    # And now you can do:
    self.print_callback("Message from Fruit: ")
6

你可以直接使用:

class Apple(Fruit):
    print_callback = staticmethod(apple_print)

或者:

class Apple(Fruit):
    print_callback = classmethod(apple_print)

在第一种情况下,你只会得到一个参数(原始参数)。在第二种情况下,你会收到两个参数,第一个参数是你调用这个方法的类。

希望这对你有帮助,而且更简短、更简单。

11

在Python中,任何在类里面定义的函数都会被认为是方法。如果你想把它们当作普通的函数来使用,就需要去找它们的一些属性,来获取原始的函数对象:

def __init__(self, *args, **kwargs):
    super(Fruit, self).__init__(*args, **kwargs)

    # The attribute name was changed in Python 3; pick whichever line matches
    # your Python version.
    callback = self.print_callback.im_func  # Python 2
    callback = self.print_callback.__func__ # Python 3

    callback("Message from Fruit: ")

撰写回答