2012-06-22 38 views
4

我最近纔開始學習Python。讓我解釋我想要完成的事情。我有這個.py腳本,基本上有幾個功能(硬編碼到腳本中),都需要添加到單個列表中,以便我可以通過簡單地使用索引運算符來獲得我需要的功能,如下所示:Pythonic,動態定義靜態定義函數列表的優雅方法?

needed_function = function_list [needed_function_index]

我在實施第一次嘗試,這導致在下面的代碼結構:

(imports) 
function_list = [] 
(other global variables) 

def function_0 = (...) 
function_list.append(function_0) 

def function_1 = (...) 
function_list.append(function_1) 

def function_2 = (...) 
function_list.append(function_2) 

(rest of code) 

但我不喜歡這樣的解決方案,因爲它是不是很優雅。我的目標是能夠簡單地將函數定義添加到腳本中(不帶追加調用),腳本將自動將其添加到函數列表中。

我想過在另一個函數中定義所有的函數,但我不認爲我會得到任何與這些。我想也許用裝飾器「標記」每個函數,但是我意識到裝飾器(如果我正確地理解它們)在每次調用函數時調用,而不是一次。

一段時間後,我想出了這個解決方案:

(imports) 
(global variables) 

def function_0 = (...) 

def function_1 = (...) 

def function_2 = (...) 

function_list= [globals()[x] for x in globals() if re.match('^function_[0-9]+$', x)] 

(rest of code) 

我喜歡它多一點作爲一個解決方案,但我與它唯一的疑慮是,我寧願,用於清潔的目的,完全定義腳本頂部的function_list。不過,我不能這樣做,因爲腳本頂部的globals()調用將不包含函數,因爲它們還沒有被定義。

也許我應該簡單地解決一個不太優雅的解決方案,或者我不是以一種慣用的方式寫我的腳本。無論如何,任何意見和建議表示讚賞。

+2

我的建議是用裝飾來做到這一點 - 我認爲這是最優雅的。他們只運行一次。 –

回答

8

你誤解了裝飾器。當函數被定義時,它們被調用一次,並且它們返回的函數是分配給函數名稱的值,並且每次都調用該函數。你可以在裝飾器中做你想要的而不會產生運行時間的開銷。

my_functions = [] 

def put_in_list(fn): 
    my_functions.append(fn) 
    return fn 

@put_in_list 
def function1(): 
    pass 

@put_in_list 
def function2(): 
    pass 

PS:無論如何,您可能不需要擔心運行時間開銷。

PPS:你也試圖優化奇怪的東西,你可能最好在文件中維護一個列表。你多久添加一次函數,以及多少思考?源文件中的列表不難更新。

+0

感謝您的回答!那很完美。 我意識到這可能看起來像一個奇怪的優化 - 優化我的腳本的性能不是我的目標,因爲它是一個非常簡單的腳本,已經很快了。我只是有這種癡迷的傾向,試圖寫出最美麗和習慣的代碼,這些東西在我開始接受更復雜的項目時可能會派上用場。 – Lanaru

0

解決此問題的一種方法是將所有這些函數放入一個容器中,然後從容器中提取函數以構建您的列表。

最Pythonic容器將是一個class。我並不是說要讓他們成爲班級的成員;只需在課堂上定義它們。

class MyFunctions(object): 
    def func0(): 
     pass 
    def func1(): 
     pass 

lst_funcs = [x for x in MyFunctions.__dict__ if not x.startswith('_')] 

但我喜歡裝飾者的方法更好;這可能是最爲Pythonic的解決方案。

1

使用裝飾不與任何開銷添加到函數調用示例:

my_list = [] 

def add_to_my_list(func): 
    print 'decorator called' 
    my_list.append(func) 
    return func 

@add_to_my_list 
def foo(): 
    print 'foo called' 

@add_to_my_list 
def bar(): 
    print 'foo called' 

print '-- done defining functions --' 
my_list[0]() 
my_list[1]()