我寫了順序地運行幾個功能,每一個取作其輸入前一個函數的輸出,從而以運行它,我要運行這行代碼清理嵌套調用
make_list(cleanup(get_text(get_page(URL))))
我只是覺得這個醜陋而且效率低下,有沒有更好的方法來進行順序函數調用?
我寫了順序地運行幾個功能,每一個取作其輸入前一個函數的輸出,從而以運行它,我要運行這行代碼清理嵌套調用
make_list(cleanup(get_text(get_page(URL))))
我只是覺得這個醜陋而且效率低下,有沒有更好的方法來進行順序函數調用?
真的,這與任何相同您想要重構常用複雜表達式或語句的情況:只需將表達式或語句轉換爲函數即可。事實上,你的表達恰好是函數調用的組合並沒有什麼區別(但在下面看到)。
所以,很明顯的事情是寫在一個地方組成的功能整合在一起的包裝功能,因此在其他地方你可以做一個簡單的調用包裝:
def get_page_list(url):
return make_list(cleanup(get_text(get_page(url))))
things = get_page_list(url)
stuff = get_page_list(another_url)
spam = get_page_list(eggs)
如果你不需要總是調用完全相同的函數鏈,你總是可以分解出你經常調用的部分。例如:
def get_clean_text(page):
return cleanup(get_text(page))
def get_clean_page(url):
return get_clean_text(get_page(url))
這個重構也將打開大門,使代碼有點冗長,但容易調試了很多,因爲它僅出現多次,一旦改爲:
def get_page_list(url):
page = get_page(url)
text = get_text(page)
cleantext = cleanup(text)
return make_list(cleantext)
如果您發現自己需要經常對組合函數進行這種重構,您總是可以編寫一個幫助程序來生成重構函數。例如:
def compose1(*funcs):
@wraps(funcs[0])
def composed(arg):
for func in reversed(funcs):
arg = func(arg)
return arg
return composed
get_page_list = compose1(make_list, cleanup, get_text, get_page)
如果你想要一個更復雜的compose
功能(即,例如,允許各地傳遞多個ARGS /返回值),它可以得到一個有點複雜的設計,所以你可能想看看周圍用於各種現有實現的PyPI和ActiveState。
你可以嘗試這樣的事情。我總是喜歡把火車殘骸分開(「Clean Code」這本書稱這些嵌套功能爲火車殘骸)。這是更容易閱讀和調試。請記住,您可能花費兩倍的時間閱讀代碼,而不是編寫代碼,以便更易於閱讀。你稍後會感謝你。
url = get_page(URL)
url_text = get_text(url)
make_list(cleanup(url_text))
# you can also encapsulate that into its own function
def build_page_list_from_url(url):
url = get_page(URL)
url_text = get_text(url)
return make_list(cleanup(url_text))
是的,這就是我正在做的 –
選項:
cleanup
和make_list
,然後用它們裝飾get_text
。你可以縮短這樣的結構有類似以下內容:
class ChainCalls(object):
def __init__(self, *funcs):
self.funcs = funcs
def __call__(self, *args, **kwargs):
result = self.funcs[-1](*args, **kwargs)
for func in self.funcs[-2::-1]:
result = func(result)
return result
def make_list(arg): return 'make_list(%s)' % arg
def cleanup(arg): return 'cleanup(%s)' % arg
def get_text(arg): return 'get_text(%s)' % arg
def get_page(arg): return 'get_page(%r)' % arg
mychain = ChainCalls(make_list, cleanup, get_text, get_page)
print(mychain('http://is.gd'))
輸出:
make_list(cleanup(get_text(get_page('http://is.gd'))))
合併多個功能爲一體?查看[代碼氣味](http://en.wikipedia.org/wiki/Code_smell)。欲瞭解更多信息,我們需要更多關於你的功能的細節。 –
我可能是一個異常,但我不覺得難以理解。而且由於你必須實際進行所有這些函數調用,所以其他任何方法都會帶來額外的開銷,儘管很小,所以我認爲任何其他方式都不會更高效。然而,調試有點困難,因爲所有的中間臨時對象...... –