EP 15 Savoir comment les fermetures interagissent avec une portée variable

  • Closure functions can refer to variables from any of the scopes in wihch they were defined.

Effective Python

Scope

Say you want to sort a list of numbers but prioritize one group of numbers to come first.

def sort_priority(values, group):
    def helper(x):
        if x in group:
            return (0, x)
        return (1, x)
    values.sort(key=helper)
In [2]: numbers = [8, 3, 1, 2, 4, 5, 7,6]

In [3]: group = {2, 3, 5, 7}

In [4]: sort_priority(numbers, group)

In [5]: print(numbers)
[2, 3, 5, 7, 1, 4, 6, 8]

Cause Scope Bug

def sort_priority2(numbers, group):
    found = False # Scope: sort_priority2
    def helper(x):
        if x in group:
            found = True # Scope: helper -- Bad
            return 0, x
        return 1, x
    numbers.sort(key=helper)
    return found
>>> l = [4, 6,2,5,7,9, 0]
>>> found = sort_priority2(l, [2,5,8])
>>> found
False
>>> l
[2, 5, 0, 4, 6, 7, 9]

  1. The current function's scope
  2. Any enclosing scope (like other containing functions)
  3. The scope of the module that contains the code(also called the global scope)
  4. The built-in scope(that contains functions like len and str)

Getting Data out

nonlocal Python 3

def sort_priority2(numbers, group):
    found = False # Scope: sort_priority2
    def helper(x):
        nonlocal found
        if x in group:
            found = True # Scope: helper -- Bad
            return 0, x
        return 1, x
    numbers.sort(key=helper)
    return found

The nonlocal statement is used to indicate that scope traversal should happen upon assiginment for a specific variable name. The only limit is that nonlocal won't traverse up to the module-level scope (to avoid polluting globals)

Recommended Posts

EP 15 Savoir comment les fermetures interagissent avec une portée variable
Note Python efficace Item 15 Savoir comment les fermetures sont liées à la portée de la fonction
Portée variable