숫자로 이뤄진 list를 정렬하되, 정렬한 리스트의 앞쪽에는 우선수위를 부여한 몇몇 숫자를 위치시켜야 한다고 가정
def sort_priority(values, group):
def helper(x):
if x in group:
return (0, x)
return (1, x)
values.sort(key=helper)
numbers = [8, 3, 1, 2, 5, 4, 7, 6]
group = [2, 3, 5, 7]
sort_priority(numbers, group)
print(numbers)
[2, 3, 5, 7, 1, 4, 6, 8]
클로저를 사용해 우선순위가 높은 원소를 발견했음을 표시하는 플래그를 설정하면 어떨까?
def sort_priority2(values, group):
found = False
def helper(x):
if x in group:
found = True
return (0, x)
return (1, x)
values.sort(key=helper)
return found
found = sort_priority2(numbers, group)
print('발견:', found)
print(numbers)
발견: False [2, 3, 5, 7, 1, 4, 6, 8]
왜 False가 나올까?
식 안에서 변수를 참조할 때 파이썬 인터프리터는 이 참조를 해결하기 위해 다음 순서로 영역을 뒤진다.
파이썬에는 클로저 밖으로 데이터를 끌어내는 특별한 구문인 nonlocal 문이 있다
def sort_priority2(values, group):
found = False
def helper(x):
nonlocal found
if x in group:
found = True
return (0, x)
return (1, x)
values.sort(key=helper)
return found
found = sort_priority2(numbers, group)
print('발견:', found)
print(numbers)
발견: True [2, 3, 5, 7, 1, 4, 6, 8]
global 문을 보완해 줄 수 있음
nonlocal을 사용하는 방식이 복잡해지면 도우미 함수로 상태를 감싸는 편이 더 낫다
class Sorter:
def __init__(self, group):
self.group = group
self.found = False
def __call__(self, x):
if x in self.group:
self.found = True
return (0, x)
return (1, x)
sorter = Sorter(group)
numbers.sort(key=sorter)
sorter.found
True