Python中的匿名内部类

时间:2015-02-07 17:26:11

标签: python

所以我有一个按钮类,点击时可以执行某些操作,但不同的按钮执行不同的功能。我想知道是否有像Python中的匿名内部类这样的东西来覆盖这样的回调而不为每种类型的按钮创建一个新的类。我知道我可以分配一个回调属性来调用这样的函数,但我只是想知道是否有一个匿名的内部类等价。

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

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

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

class Button {

    Button() {
        // set image here
    }

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

2 个答案:

答案 0 :(得分:1)

当然,你可以(虽然可能不应该)只使用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

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

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

    我的意思是这样的:

    class Greeter:
        def __init__(self, name):
            self.name = name
        def greet(self):
            print('Hello, {.name}'.format(self))
    
  2. 您只需将实例属性设置为所需的回调:

    button.callback = new_callback
    

答案 1 :(得分:0)

你不需要创建一个匿名类 - python允许你用任何可调用的方法替换方法(事实上,任何动态的对象):

Button.update = lambda x: x*x 

完全有效。

编辑: Java方法实际上并没有使你免于生成任何类 - 该类只是没有名称,因此没有"有益于"这样做。