2015-02-07 82 views
1

所以我有一個按鈕類,它在單擊時執行某些操作,但不同的按鈕執行不同的功能。我想知道是否有像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 
     } 
    } 
} 
+0

一般情況下,我得到的感覺是Python的方式做,這是創建一個按鈕基類,然後只是重寫東東方法d爲每個單獨的按鈕覆蓋...(但是,我不是Java程序員,所以我可能會錯誤地解釋你想做什麼......) – mgilson 2015-02-07 17:35:19

+0

關於Java方法,我認爲它確實創建了一個類,只是它的範圍受到了限制。在Python中,你可以在函數內部創建類,這很類似。請注意,我實際上是指類,而不是實例! – 2015-02-07 17:38:35

+2

好吧,它們並不完全等價,在Python中,函數內的類會爲每次運行創建一個全新的類對象,而在Java中它更像是一個Python閉包。 – 2015-02-07 17:43:22

回答

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 
    
+0

謝謝,這可能是最接近我的想法。 – 2015-02-07 17:43:23

+0

@MalikBrahimi我已經添加了我提到的裝飾解決方案,可以在定義本地類時避免額外的分配。但是,我個人會避免這種事情。 – Bakuriu 2015-02-07 17:49:30

0

你不需要做一個匿名類 - 蟒蛇,您可以替換任何可調用的(其實,任何的飛行物體)方法:

Button.update = lambda x: x*x 

是完全有效的。

編輯: Java方法實際上並不能節省您生成任何類 - 該類沒有名稱,所以沒有「好處」這樣做。

+0

首先,我不明白x在這種情況下對於lambda是什麼。其次,每次初始化之後,我都必須改變方法。 – 2015-02-07 17:38:56

+0

我的編輯幫助? – 2015-02-07 17:40:51

+0

不,它確實沒有。我正在尋找一個確切的等價物,而不是一些艱鉅的解決方法。 – 2015-02-07 17:42:17