[Effective Python] | September 19, 2020
Effective Python: Second Edition 내용 정리
numbers = [1, 2, 3, 4, 5, 6]
group = {1, 3, 5}
def sort_group(values, group):
def helper(x):
if x in group:
return (0, x)
return (1, x)
values.sort(key=helper)
sort_group(numbers, group)
numbers
>>> [1, 3, 5, 2, 4, 6]
numbers = [1, 2, 3, 4, 5, 6]
group = {1, 3, 5}
def sort_group(values, group):
group_check = False
def helper(x):
if x in group:
group_check = True
return (0, x)
return (1, x)
values.sort(key=helper)
return group_check
sort_group(numbers, group)
>>> False
numbers
>>> [1, 3, 5, 2, 4, 6]
⇒ group_check가 True가 될 것으로 예상했지만, False가 나왔다. 어떻게 된 것일까?
아래의 코드를 다시 보면, sort_group에서 정의된 group_check는 False로 남아있고, helper 함수 내에서의 group_check는 새로운 변수를 새로 할당한 것으로 취급한다.
def sort_group(values, group):
group_check = False # scope: 'sort_group'
def helper(x):
if x in group:
group_check = True #새로운 변수 할당(scope: 'helper')
return (0, x)
return (1, x)
values.sort(key=helper)
return group_check
nonlocal은 module-level scope까지는 가지 않는다. (global 변수는 건드리지 않기 위해)
module scope까지 바로 가는 global statement와 상호보완이 가능하다.
numbers = [1, 2, 3, 4, 5, 6]
group = {1, 3, 5}
def sort_group(values, group):
group_check = False
def helper(x):
nonlocal group_check #추가
if x in group:
group_check = True
return (0, x)
return (1, x)
values.sort(key=helper)
return group_check
sort_group(numbers, group)
>>> True
numbers
>>> [1, 3, 5, 2, 4, 6]
nonlocal
을 사용할 때 주의하라.nonlocal의 사용이 복잡해지면, helper class로 상태를 넣어두는 것이 낫다.
(__call__
method에 대해서는 Item 38 참조)
numbers = [1, 2, 3, 4, 5, 6]
group = {1, 3, 5}
class Sorter:
def __init__(self, group):
self.group = group
self.group_check = False
def __call__(self, x):
if x in self.group:
self.group_check = True
return (0, x)
return (1, x)
sorter = Sorter(group)
numbers.sort(key=sorter)
assert sorter.group_check is True
numbers
>>> [1, 3, 5, 2, 4, 6]