파이썬에서 and와 or는 예상대로 불리언 논리를 수행합니다. 그러나 불리언 값을 돌려주지 않습니다; 대신에, 비교중인 실제 값중의 하나를 돌려줍니다.
예제 4.15. and 소개
- >>> 'a' and 'b' ①
- 'b'
>>> '' and 'b' ② - ''
>>> 'a' and 'b' and 'c' ③
'c'
① and를 사용할 때, 값들은 불리언 문맥에서 왼쪽에서 오른쪽으로 가면서 평가됩니다. 0, '', [], (), {}, 그리고 None은 불리언 문맥에서 거짓입니다; 다른 것들은 모두 참입니다. 음, 거의 모든 것입니다. 기본값으로, 클래스의 실체는 불리언 문맥에서 참입니다. 그러나 특별한 메쏘드를 클래스에 설정하면 그 실체가 거짓으로 평가되도록 만들 수 있습니다. 클래스와 특수 메쏘드에 관한 모든 것은 제 5 장에서 배우겠습니다. 불리언 문맥에서 모든 값이 참이면 and는 가장 마지막 값을 돌려줍니다. 이 경우, and는 'a'를 평가하는데, 그 값은 참이며, 다음 'b'를 평가하는데, 그 값이 참입니다. 그래서 'b'를 돌려줍니다.
② 불리언 문맥에서 무엇이든 거짓이면 and는 그 첫 거짓 값을 돌려줍니다. 이 경우, '' 가 첫 거짓 값입니다.
③ 모든 값이 참입니다. 그래서 and는 마지막 값인 'c'를 돌려줍니다.
예제 4.16. or 소개
- >>> 'a' or 'b' ①
- 'a'
>>> '' or 'b' ② 'b'
>>> '' or [] or {} ③
{}
>>> def sidefx():
... print "in sidefx()"
... return 1
>>> 'a' or sidefx() ④
'a'
① or을 사용할 때, 값은 불리언 문맥에서 왼쪽에서 오른쪽으로 가면서 평가됩니다. and와 똑 같이 말입니다. 어떤 값이 참이면 or은 즉시 그 값을 돌려줍니다. 이 경우, 'a'가 첫 참 값입니다.
② or은 ''를 평가하고, 그 값은 거짓입니다. 다음 'b'를 평가하는데, 그 값은 참입니다. 그래서 'b'를 돌려줍니다.
③ 모든 값이 거짓이면 or는 마지막 값을 돌려줍니다. or은 ''을 평가하는데, 이 값은 거짓입니다. 다음 []가 평가되며, 그 값은 거짓입니다. 다음 {}가 평가되는데, 그 값은 거짓입니다. 그래서 {}을 돌려줍니다.
④ 주목하세요. or은 불리언 문맥에서 참인 값을 발견할 때까지만 값들을 평가합니다. 그리고 나머지는 무시합니다. 어떤 값들은 부작용을 가질 수 있기 때문에 이 구별은 중요합니다. 여기에서 sidefx 함수는 절대로 호출되지 않습니다. 왜냐하면 or은 'a'를 평가하고, 그 값은 참이므로, 즉시 'a'를 돌려주기 때문입니다.
여러분이 C 해커라면 분명히 bool ? a : b 표현식을 잘 아실 겁니다. 이 표현식은 bool이 참이면 a로 평가되고, 그렇지 않으면 b로 평가됩니다. 파이썬에서 and와 or의 작동 방식 때문에, 같은 일을 할 수 있습니다.
4.6.1. and-or 트릭을 사용하기
예제 4.17. and-or 트릭
- >>> a = "first"
- >>> b = "second"
>>> 1 and a or b ①
'first'
>>> 0 and a or b ②
'second'
① 이 구문은 C의 bool ? a : b 표현식과 비슷합니다. 전체 표현식은 왼쪽에서 오른쪽으로 평가됩니다. 그래서 and가 먼저 평가됩니다. 1 and 'first'는 'first'로 평가되고, 다음 'first' or 'second'는 'first'로 평가됩니다.
② 0 and 'first'는 False로 평가되고, 다음 0 or 'second'는 'second'로 평가됩니다.
그렇지만, 이 파이썬 표현식은 단순히 불리언 논리에 불과하고, 언어의 특별한 구조가 아니기 때문에, 파이썬의 and-or 트릭과 C의 bool ? a : b 구문 사이에 아주 중대한 차이가 하나 있습니다. a의 값이 거짓이면 표현식은 예상대로 작동하지 않습니다 (본인은 과연 이 함정에 빠졌을까요? 몇 번이나 빠졌을까요?)
예제 4.18. and-or 트릭이 실패할 때
- >>> a = ""
- >>> b = "second"
>>> 1 and a or b ①
'second'
① a는 빈 문자열이므로, 파이썬은 불리언 문맥에서 거짓으로 간주하고, 1 and ''는 ''로 평가되며, 다음 '' or 'second'는 'second'로 평가됩니다. 이런! 원한게 아니군요.
불리언 문맥에서 a가 거짓으로 평가될 경우, and-or 트릭인 "bool and a or b"는 C 표현식인 "bool ? a : b"와 똑같이 작동하지 않습니다.
그래서 and-or 트릭 뒤의 진짜 트릭은 a의 값이 절대로 거짓이 되지 않도록 확인하는 것입니다. 이렇게 하는 일반적인 방법은 a를 [a]에 넣고 b를 [b]에 넣은 다음, 반환된 리스트의 첫 원소를 받는 것입니다. 그 원소는 a나 b가 될 것입니다.
예제 4.19. 안전하게 and-or 트릭을 사용하는법
- >>> a = ""
- >>> b = "second"
>>> (1 and [a] or [b])[0] ①
''
① [a]는 빈 리스트가 아니므로, 절대 거짓이 아닙니다. a가 0이나 '' 또는 기타 다른 거짓 값이라도 원소가 한개 있으므로 리스트 [a]는 참입니다.
지금까지는 이 트릭이 그 가치에 비해 너무 복잡해 보일 수도 있습니다. 어쨋든 같은 일을 if 서술문으로 할 수 있습니다. 그런데 왜 이렇게 복잡하게 하는가? 음, 많은 경우, 두 개의 상수 값 중에 하나를 선택합니다. 그래서 더 간단한 구문을 사용할 수 있으면 신경쓰지 않아도 됩니다. 왜냐하면 a 값이 언제나 참이라는 사실을 알기 때문입니다. 더 복잡한 안전한 형태를 사용할 필요가 있다면 그래야 할 충분한 이유가 있습니다. 예를 들어, 어떤 경우는 파이썬에서 lambda 함수 같은 경우 if 서술문이 허용되지 않습니다.
'Python' 카테고리의 다른 글
4.8. 하나로 모두 합치기 - apihelper.py (0) | 2012.01.11 |
---|---|
4.7. lambda 함수 사용하기 (0) | 2012.01.11 |
4.4. getattr로 객체 참조점 얻는 방법 (0) | 2012.01.11 |
4.3. type, str, dir, callable 그리고 기타 내장 함수들 (0) | 2012.01.11 |
4. 강력한 내부검사 (0) | 2012.01.11 |