bslatkin / effectivepython

Effective Python: Second Edition — Source Code and Errata for the Book
https://effectivepython.com
2.24k stars 718 forks source link

Item 15, P32, definition of closure function seems wrong . #45

Closed xueying-tan closed 7 years ago

xueying-tan commented 7 years ago
def sort_priority(values, group):
    def helper(x):
        if x in group:
            return (0, x)
        return (1, x)
    values.sort(key=helper)

if '__main__' == __name__:
     numbers = [8,3,1,2,5,4,7,6]
     group =[2,3,5,7]
     sort_priority(numbers,group)  # return [2, 3, 5, 7, 1, 4, 6, 8]
     print(numbers)
     print(sort_priority.__closure__) # return None

There is a line in the middle of page 32, which says : This is how the sort method can accept a closure function as the key argument, But actually function helper is only a nested function rather than a closure function. A closure function must be a nested function, but a nested function is not necessarily a closure function.

To be a closure function

  1. It itself must be a nested function.
  2. It must refer to a value defined in the enclosing function.
  3. the enclosing function must return the nested function.

Obviously helper function doesn't meet the above #3 , it isn't returned by the enclosing function. Also, if helper is a closure function,sort_priority.__closure__ should return something like (<cell at 0x10d95a868: int object at 0x7f99e340bf68>, <cell at 0x10da08750: int object at 0x7f99e340bf50> other than None

ZER0921 commented 7 years ago
def sort_priority(values, group):
    def helper(x):
        if x in group:
            return (0, x)
        return (1, x)
    values.sort(key=helper)
    print(helper.__closure__)

Maybe helper.__closure__ will return something you expected
bslatkin commented 7 years ago

The closure is helper in this case, which "closes" over the group variable. @ZER0921's suggestion is right on.