簡體   English   中英

Python 的 nonlocal 關鍵字 - 這是一個好習慣嗎?

[英]Python's nonlocal keyword - is this good practice?

考慮一個簡單的情況,例如在 BST 中找到第 k 個最小的元素。

在我下面的解決方案中:

class Solution:
    def kthSmallest(self, root: TreeNode, k: int) -> int:
        i = 0
        ans = -1
        def traverse_inorder(root):
            nonlocal i
            nonlocal ans
            if not root:
                return
            traverse_inorder(root.left)
            i += 1
            if i == k:
                ans = root.val
                return
            traverse_inorder(root.right)
        traverse_inorder(root)
        return ans

我使用nonlocal for ians是好的做法嗎? 我這樣做是為了跟蹤在到達最左邊的節點(最小值)后我遍歷了多少元素。

另一種解決方案是將ians作為 class 的成員變量:

class Solution:
    def kthSmallest(self, root: TreeNode, k: int) -> int:
        self.i = 0
        self.ans = -1
        def traverse_inorder(root):
            # etc etc

兩種方法是否等效? 一種做法比另一種更好,為什么?

我認為在你描述的情況下, nonlocal方法客觀上比你展示的另一種方法更有意義。 您的目標是在您的 function 之外有一個計數器,並在找到結果時跟蹤結果,無論您在遞歸中的哪個位置。

nonlocal將該信息完全封裝在一個命名空間中,該命名空間專用於您的外部 function 的特定運行。 這里真的沒有缺點。

使用實例屬性使使用該實例的任何人都可以使用該信息。 這在概念上是不必要的,速度稍慢,而且不是線程安全的。 雖然在 Python 中線程安全通常不是問題,但它確實使您的代碼的健壯性大大降低。 在這和封裝之間,我肯定會遠離這種方法。

我在這里建議第三種可能性:使用返回值。 在這種情況下,您真的不需要任何外部命名空間。 我不一定推薦使用nonlocal ,但值得一提。 這是一個示例實現,您可以看到它比您的解決方案更詳細:

class Solution:
    def kthSmallest(self, root: TreeNode, k: int) -> int:
        def traverse_inorder(root, target):
            if not root:
                return 0, None
            left_count, item = traverse_inorder(root.left, target)
            if left_count == target - 1:
                 return left_count + 1, root.val
            elif left_count < target:
                 right_count, item = traverse_inorder(root.right, target - left_count - 1)
                 return left_count + right_count + 1, item
            else:  # left_count == target
                 return left_count, item
        count, ans = traverse_inorder(root, k)
        if count < k:
            raise ValueError('Insufficient elements')
        return ans

有很多方法可以用返回值來做到這一點。 在這里,我計算每個子樹中的元素數,直到目標值。 僅當找到確切數量的元素時才返回非無項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM