编写一个接受Python回调的类?

时间:2009-10-14 17:25:40

标签: python callback

我需要编写一个允许子类使用函数名称设置属性的类。然后,该函数必须可以从类的实例中调用。

例如,我说我需要编写一个Fruit类,子类可以在欢迎消息中传递。 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: ")

我需要公开一个可以被这段代码使用的API(要清楚,这段代码不能改变,说它是第三方代码):

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

class Apple(Fruit):
    print_callback = apple_print

如果我跑:

mac = Apple()

我想得到:

  

来自Fruit的消息:我是Apple!

相反,我得到:

  

TypeError:apple_print()只需1个参数(给定2个)

我认为这是因为self作为第一个参数传入。

那么如何编写Fruit类呢?谢谢!

5 个答案:

答案 0 :(得分:8)

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: ")

答案 1 :(得分:3)

您可以直接使用:

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

或:

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

在第一种情况下,您只能获得一个参数(原始参数)。在第二个中,您将收到两个参数,其中第一个将是调用它的类。

希望这有所帮助,而且更短,更简单。

答案 2 :(得分:2)

已更新:合并abourget's suggestion以使用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: ")

答案 3 :(得分:1)

当我发现这个问题时,我正在寻找更像这样的东西:

class Something:
    def my_callback(self, arg_a):
        print arg_a

class SomethingElse:
    def __init__(self, callback):
        self.callback = callback

something = Something()
something_else = SomethingElse(something.my_callback)
something_else.callback("It works...")

答案 4 :(得分:0)

还有一些带有元类的污垢解决方案:

def apple_print(f):
    print "Apple " + f

class FruitMeta(type):
    def __new__(cls, name, bases, dct):
        func = dct["print_callback"]
        dct["print_callback"]=lambda x,f,func=func: func(f)
        return type.__new__(cls,name,bases,dct)

class Fruit(object):
    __metaclass__ = FruitMeta
    print_callback = None
    def __init__(self):
        super(Fruit,self).__init__()
        self.print_callback("Msg ")

class Apple(Fruit):
    print_callback = apple_print

mac = Apple()here

它在创建之前操纵类!