defbublle_sort(a): for _ inrange(len(a)): # 0부터 a의 길이 미만의 숫자를 포함하는 range 객체 생성 for i inrange(1, len(a)): if a[i] < a[i-1]: a[i-1], a[i] = a[i], a[i-1] # 맞바꾸기
파이썬은 한 문장 안에서 여러 값을 대입할 수 있는 언패킹이라는 특별한 문법 제공 한다. 파이썬 언패킹은 일반화돼 있으므로 모든 이터러블에 적용 가능. 이터러블이 여러 계층으로 내포된 경우에도 언패킹을 적용할 수 있다. 인덱스를 사용해 시퀀스 내부에 접근하는 대신 언패킹을 사용해 시각적인 잡음을 줄이고 코드를 더 명확하게 만들라.
Better way 7. range 보다는 enumerate를 사용하라.
range
정수 집합을 이터레이션하는 루프가 필요할때 유용
1 2 3
flavor_list = ['바닐라', '초콜릿', '피칸', '딸기'] for flavor in flavor_list: print(f'{flavor} 맛있어요.')
1 2 3 4
flavor_list = ['바닐라', '초콜릿', '피칸', '딸기'] for i inrange(len(flavor_list)): flavor = flavor_list[i] print(f'{i+1}: {flavor}')
list 길이를 알아야 하고 인덱스를 사용해 배열에 접근해야함
단계가 여러개라 코드 읽기 어려움
enumerate
1 2
for i, flavor inenumerate(flavor_list): print(f'{i+1}: {flavor}')
range의 단점을 해결할 수 있는 enumerate 내장 함수 제공
enumerate가 넘겨주는 쌍을 for문에서 간결하게 언패킹
enumerate를 사용하면 이터레이터에 대해 루프를 돌면서 이터레이터에서 가져오는 원소의 인덱스까지 얻는 코드를 간결하게 작성할 수 있다. range에 대해 루프를 돌면서 시퀀스의 원소를 인덱스로 가져오기보다는 enumerate를 사용하라. enumerate의 두번째 파라미터로 어디부터 원소를 가져오기 시작할지 지정할수 있다.(디폴트는 0이다.)
Better way 8. 여러 이터레이터에 대해 나란히 루프를 수행하려면 zip을 사용하라.
리스트 컴프리헨션
1 2 3
names = ['Cecila', '남궁민수', 'zoe'] counts = [len(n) for n in names] print(counts)
반복되거나 특정 조건을 만족하는 리스트를 보다 쉽게 만들어 내기 위한 방법
대괄호 [] 로 감싸고 내부에 for문과 if 문을 사용하여 반복하며 조건에 만족하는 것만 리스트로 생성
names = ['Cecila', '남궁민수', 'zoe'] counts = [len(n) for n in names] max_count = 0 longest_name = None
for i inrange(len(names)): count = counts[i] if count > max_count: longest_name = names[i] max_count = count
print(longest_name)
step 2) enumerate 사용
1 2 3 4 5 6 7
for i, name inenumerate(names): count = counts[i] if count > max_count: longest_name = name max_count = count
print(longest_name)
step 3) zip 사용
1 2 3 4 5 6
for name, count inzip(names, counts): if count > max_count: longest_name = name max_count = count
print(longest_name)
step 4) zip_longest
1 2 3 4 5
import itertools ...
for name, count in itertools.zip_longest(names, counts): print(f'{name}: {count}')
zip 내장함수를 사용해 여러 이터레이터를 나란히 이터레이션할 수 있다. zip은 튜플을 지연계산하는 제네레이터를 만든다. 따라서 무한히 긴 입력에도 zip 을 쓸수 있다. 입력 이터레이터의 길이가 서로 다르면 zip은 아무런 경고도 없이 가장 짧은 이터레이터 길이까지만 튜플을 내놓고 더 긴 이터레이터의 나머지 원소는 무시한다. 가장 짧은 이터레이터에 맞춰 길이를 제한하지 않고 길이가 서로 다른 이터레이터에 대해 루프를 수행하려면 itertools 내장모듈의 zip_longes 함수를 사용하라.
Better way 9. for나 while 루프 뒤에 else 블록을 사용하지 말라.
1 2 3 4
for i inrange(3): # 0부터 3미만 숫자까지 range를 만듬 print('loop', i) else: # 반복 수행되는 루프 블록 바로 다음에 else 블록 추가 가능 print('Else block!')
루프가 정상적으로 완료되지 않으면 이 블록을 실행하라 는 뜻이 아님
파이썬에서 루프와 같은 간단한 구성 요소는 그 자체로 의미가 명확해야 함
루프 뒤에 오는 else 블록은 루프가 반복되는 도중에 break를 만나지 않은 경우에만 실행된다. 동작이 직관적이지 않고 혼동을 야기할 수 있으므로 루프 뒤에 else 블록을 사용하지 말라.
대입식에서는 왈러스 연산자를 사용해 하나의 식 안에서 변수 이름에 값을 대입하면서 이 값을 평가할 수 있고 중복을 줄일수 있다. 대입식이 더 큰 식의 일부분으로 쓰일 때는 괄호로 둘러싸야 한다. 파이썬에서는 switch/case 문이나 do/while 루프를 쓸 수 없지만, 대입식을 사용하면 이런 기능을 더 깔끔하게 흉내 낼 수 있다. 코드가 못생기게 보이기 시작한다면 왈러스 연산자를 사용해 가능 한 그런 요소를 없애기 위해 노력할 것을 권장한다.