所以我有一个按钮类,当单击该按钮类时会执行某些操作,但是不同的按钮执行不同的功能。我想知道Python中是否存在诸如匿名内部类之类的东西来覆盖此类回调,而不必为每种类型的按钮创建新的类。我知道我可以分配一个回调属性来调用这样的函数,但是我只是想知道是否有一个匿名内部类等效项。

class Button:
    def __init__(self):
        # set image here

    def update(self):
        if mouse_clicked():
            # do something


在Java中,我可以创建匿名内部类来覆盖update方法以关闭,播放,暂停和所有其他按钮,而无需创建完全不同的类。

class Button {

    Button() {
        // set image here
    }

    public void update() {
        if mouse_clicked() {
            // do something
        }
    }
}

最佳答案

当然,您可以(尽管可能不应该)仅使用type

In [1]: class Button:
   ...:     def callback(self):
   ...:         print('Hello')
   ...:


In [2]: button = type('', (Button,), {'callback': lambda self: print('World')})()

In [3]: button.callback()
World


您可能更希望在表达式之外定义函数,以便避免对代码进行代码搜索:

In [5]: def callback(self):
   ...:     print('World')
   ...: button = type('', (Button,), {'callback': callback})()
   ...:

In [6]: button.callback()
World


这确实可以完成Java所做的事情,但是这样做的意义更加明确,因此语法也更加繁琐。实际上,您可以在python中定义本地类:

In [7]: def function():
   ...:     class MyButton(Button):
   ...:         def callback(self):
   ...:             print('Hello, from a local class!')
   ...:     return MyButton()
   ...:

In [8]: button = function()

In [9]: button.callback()
Hello, from a local class!


与Java的唯一区别在于,您必须为该类命名并使用它来创建实例。使用装饰器可以避免最后一步:

def auto_instantiator(*args, **kwargs):
    def decorator(cls):
        return cls(*args, **kwargs)
    return decorator


用作:

In [2]: class Button:
   ...:     def callback(self):
   ...:         print('Button')
   ...:

In [3]: @auto_instantiator()   # here args that should be passed to __init__
   ...: class button(Button):
   ...:     def callback(self):
   ...:         print('New Button')
   ...: # no need for button = button(...)

In [4]: button.callback()    # button is an *instance* of the button class
New Button


但是,根据您将如何使用该方法,我建议使用两种不同的方法来解决该问题:


实际上,除了某些数据外,按钮的所有操作都是相同的。在这种情况下,最好创建一个实例属性(或属性)来保存该数据,然后更改数据而不是方法:

我的意思是这样的:

class Greeter:
    def __init__(self, name):
        self.name = name
    def greet(self):
        print('Hello, {.name}'.format(self))

您可以将instance属性设置为所需的回调:

button.callback = new_callback

07-27 19:25