[英]When is it good to use nested functions in Python?
我不是指閉包,其中外部 function 返回內部 function,或者特別是記憶。 有幾個例子我想寫一個遞歸的 function,也許有記憶,在外部 function 中初始化一個字典或一些其他數據結構似乎更簡單,然后有一個遞歸助手 function 寫入和訪問字典和外部 function 的 arguments。這就是我的意思——
def foo(arr, l):
cache = {}
result = []
def recursive_foo_helper(i, j, k):
# some code that depends on arr, l, i, j, k, cache, and result
for (x, y) in arr:
if recursive_foo_helper(x, y, k):
return result
return None
而不是用一些超長簽名單獨聲明 helper function,例如,
recursive_foo_helper(arr, l, i, j, k, cache={}, result=[])
我讀過這樣做是記憶化的標准,但我很好奇是否就是否可以僅對遞歸輔助函數執行此操作達成共識。
有很多好的理由。 就個人而言,我經常使用嵌套函數來保持命名空間的整潔。 它在對象方法中特別有用:
class Foo(object):
def bar(self):
def baz(val):
return val
return [ baz(i) for i in range(1,101) ]
如果我在bar
之外聲明baz
,我要么需要將其設為Foo
的方法,要么將其公開給整個包。
我使用嵌套函數從列表中查找匹配項:
def get_exact(data, key, match):
def is_match(item):
if (key in item) and (item[key].lower() == match.lower()):
return item
return False
return [i for i in data if is_match(i)]
項目中沒有其他調用需要使用is_match(item)
,那么為什么要單獨聲明呢?
但是,我會說,對於我的示例,在get_exact()
is_match()
在 10,000 次迭代中運行速度確實快了約 0.04 秒。
def is_match(item, key, match):
if (key in item) and (item[key].lower() == match.lower()):
return item
return False
def get_exact(data, key, match):
return [i for i in data if is_match(i, key, match)]
我通常使用閉包,但是您建議的另一種方式(我有時稱為 Wrapper)也非常有用,並且根據我的個人經驗,它可以正常工作。 我從來沒有人告訴我要避免這種風格。 如果您的代碼有效並且可讀(我認為是這樣),那就去吧!
我想說使用你建議的閉包更干凈,但如果你想重新綁定引用,確實需要nonlocal
中的 nonlocal 關鍵字。 對於可變對象,顯然可以修改它們。
同時,在 Python2 中看到 defaultarg hacks/idioms 是很常見的
嵌套函數的一個(也許是唯一的)缺點是難以進行單元測試。
為了確保緩存不會無限增長,您還需要一種刪除項目的方法(例如最近最少使用的)
我認為嵌套函數非常適合遞歸。 考慮以下函數來搜索 BST 是否包含具有數據target
的節點:
def contains_target(self, target) -> bool:
def _contains_target(node, target):
if node is not None:
found = False
found = _contains_target(node.left, target)
if found:
return True
found = _contains_target(node.right, target)
if found:
return True
found = target == node.data
return found
else:
return False
# Begin at the root
return _contains_target(self.root, target)
我發現這更可取,因為當第一次運行嵌入式輔助函數時,您可以為一個或所有參數設置一個初始化參數。 在這種情況下,考慮的第一個節點是樹的根節點。
嵌套函數的一個缺點是在測試方面。
def compute_sequence(sequence):
"""Compute blabla on sequence"""
def compute_element(element):
"""Compute blabla on element"""
return element * 2
sequence = sequence + 1 # global treatment
return [compute_element(element) for element in sequence]
問題:如何測試 compute_element? 你如何訪問它的文檔字符串?
意見:如果您選中“導入此”,您將看到:
Python 的 Zen,作者 Tim Peters [...] Flat 優於嵌套。 [...]
即使我今天大量使用嵌套函數,我也覺得使用它們很不自在 Peace out
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.