python

왜 리스트 컴프리헨션에 if만 있을때와 else도 있을 때 문법이 다를까?

게으른 the lazy 2022. 10. 23. 13:54

참고한 곳: 스택오버플로우

 

리스트 컴프리헨션(LC)에 if만 있을 때는 왜 if가 맨 뒤로 가고

[i**2 for i in range(10) if i%3 == 0]

 

if와 else가 모두 쓰일 때에는 왜 if-else가 for보다 앞에 올까?

[i**2 if i%3 == 0 else i*2 for i in range(10)]

 

한줄요약: if만 있는 것은 filter이고, if-else는 3항 연산자이기 때문이다.

 


 

if만 있는 경우, if는 filter의 역할이다. 즉, filter를 통과한 것만 살아남는다. LC의 문법은 filter를 뒤에 쓴다.

[<expr> for <index> in <iterable> if <condition>]

실제로 공식 문서를 보면 LC 뒤에 if가 추가될 수 있다고만 나오지, else는 언급되지 않는다.

 


 

if-else는 그 자체로 하나의 연산자이다. 구체적으로 말하자면 조건에 따라 분기 가능한 3항 연산자이다. 연산자는 항상 어떤 값을 반환해야 하므로, if를 만족하지 못하더라도 어떤 값을 반환하기 위해 반드시 else가 필요하다. LC의 문법은 아래와 같은데,

[<expr> for <index> in <iterable>]

if-else로 이루어진 3항 연산자는 <expr> 위치에 들어간다.

[<expr1> if <cond> else <expr2> for <index> in <iterable>]

 


 

3항 연산자 사용 시 주의할 것이 있다. 아래는 왜 안될까?

print('yes') if foo == bar else pass

3항 연산자는 반드시 값을 반환해야 한다. 하지만 pass는 값이 아니며, 아무것도 반환하지 않는다. 따라서 아래처럼 써야 한다.

print('yes') if foo == bar else None # works fine, returns None
print('yes') if foo == bar else ... # works fine, returns ...(Ellipsis)

그럼 이건 왜 될까?

print('yes') if foo == bar else print('nope')

답은 간단하다. print가 None을 반환하기 때문이다.

>>> foo = 1
>>> bar = 0
>>> print(print('yes') if foo == bar else print('nope'))
nope
None

 

 

- 게으른

 

# 도움 주신 엘카인 님께 감사 말씀 드립니다.

# 잘못된 내용이 있다면 댓글 적어주세요.