python lambda function, list comprehension, locals, f-string

이성준·2023년 6월 27일
0

책 [파이썬 알고리즘 인터뷰]의 3장에서 나온 파이썬 관련요소의 나머지를 한번 뜯어보겠다.
먼저 은연중 넘어간 Lambda Function이다.

1. lambda Function

사실 실제로 코딩을 할때, 이렇게 간단한 함수를 단독으로 사용하는 경우는 많이 없다. 따라서 사용경험은 많이 없는데, 이 기회에 정리를 해두면 좋을것 같아서 정리를 해두겠다.
람다는 간단한 함수를 하나의 line으로 간편하게 작성해서 사용하기 위해서 사용한다.
lambda의 기본적인 구성요소는 다음과 같다.
lambda <매개변수>: <결과 표현식> <조건>
위에서 언급한 lambda function을 활용하는 예시를 살펴보자.

f = (lambda n,m: n+m if n>0 else 0)
print(f(-1,2))


주의해야할 점은 다음과 같다.

  • 뒤에 조건에 if와 else는 하나의 쌍이다. 즉, 조건문은 다음과 같은 형태여야한다.
    if 조건 else 결과표현식이 될 value
    즉, 다음과 같이 사용하면 오류가 발생한다.
f = (lamda n,m: n+m if n>0 else n=0)
or
f = (lambda n,m: n+m if n>0 else if m>0 ...)
# lambda function에서는 else if 를 사용할 수 없음
or
f = (lambda n,m: n+m if n>0 n=4 else n=0)

따라서 다중조건이 필요한 경우 lambda 함수를 작성하는 것은 고려하지 말자.

map() filter() reduce() 클래스는 함수를 매개변수로 받아서 결과를 반환하는데, 이때 람다함수를 자주 사용하곤한다.

2. list comprehension
list comprehension은 꽤나 많이 사용해봤다고 생각했다. 책을 읽고 list comprehension을 dictionary에서 활용한 것을 보는 순간 큰 착각이였다는 것을 깨달았다.

먼저, list comprehension은 무엇인가 하면 리스트를 더 간편하게 구성하고자 사용하는 파이썬 구문이다.
따라서 기본적인 구성요소는 다음과 같다.
[ (변수) for (변수) in (iterable객체) if문]

예시를 살펴보자 가볍게 1부터 10까지 짝수만을 리스트에 넣어보겠다. 다음과 같이 작성할 수 있을 것이다.

new = []
for i in range(1,11):
    if i%2==0:
        new.append(i)
print(new)

이를 단번에 줄일 수 있다.
print([new for new in range(1,11) if new % 2 == 0])

위에처럼 리스트를 생성하면 생각을 하지 않고, 리스트를 생성할 수 있다. 하지만 코드가 길어지는 원인이 되기 때문에, 아래처럼 리스트 comprehension을 작성하도록 하자.

list comprehension에서도 조건문을 여러개 작성할 수 있다. 하지만 if문을 사용할때
[n for n in range(1, 31) if n % 2 == 0 if n % 3 == 0] 왼쪽과 같이 작성을 해야하고 이는 and로 연결돼있다. 가독성을 위해 and로 연결하고자 하면 오류를 발생시키고 or는 애초에 사용조차 할 수 없다.


결론적으로, 모든 적당한 것이 좋다. 여러 조건문을 사용해서 리스트를 구성해야할때는, 굳이 list comprehension을 작성하려고 하지말자 !

위의 구조를 이용해서 다음과 같이 리스트 컴프리헨션을 작성할 수도 있다.
[i if i%2==0 else 'odd' for i in range(5)]

위의 그림을 참고하면 (if문이 True일때) if ~ else (if문이 False일때)라는 명령어에 익숙해지고 이를 리스트 컴프리헨션안에 넣을수도 있다.

  • list comprehension을 꼭 리스트가 아닌 다른 자료구조(e.g. tuple, set, dictionary)에도 사용할 수있다.
set_a = { n for n in range(1,10) }
print(set_a)
print(type(set_a))

from string import ascii_lowercase as Lower

print(Lower)
dict_a = {c: n for c, n in zip(Lower,range(1,27))}
print(dict_a)

자 그렇다면 이제, tuple에 대해서 한번 해보자 !

tup_a = ( n for n in range(1,10) )
print(tup_a)
print(type(tup_a))


자연스럽게 위와 같이 작성하고 실행한 나는 예상치 못한 결과에 당황했다.
알고보니 이는 generator를 만드는 generator comprehension이었다.

이것이 바로 generator를 만들때 yield 구문을 사용하지 않고 generator를 만들 수 있는 방법이다.

tuple을 만들기 위해서는 tuple()을 사용해주면된다.

tup_a = tuple(( n for n in range(1,10) ))
print(tup_a)
print(type(tup_a))

3. locals()

locals()는 모든 지역변수를 조회할 수 있는 강력한 명령으로써 디버깅에 많은 도움이 된다. 특히 local scope에 제한해 정보를 조회하기 때문에 더욱 도움이 된다. 한번 Decorator 포스팅에서 사용한 calculator class를 이용해서 사용해보겠다.


from typing import Tuple
import pprint

class Calculator:
    def __init__(self, func):
        self.func = func

    def __call__(self,*args,**kwargs):
        print("연산시작")
        self.func(args)
        print("연산종료")
    


@Calculator
def add(tup: Tuple): # 2. add function 선언
    summation = 0
    for i in tup:
        summation = summation + i

    print(summation)
    print(locals())

add(1,3)

딕셔너리 형태로 함수 내부의 로컬 변수들을 출력해 줌을 볼 수 있다.

4. f-string
나는 출력을 할때 보통 format을 이용해서 출력을 진행했다.(알 것이 수두룩 빽빽인데, 출력하는 방법만큼은 통일하자.. 라는 생각을 했다.) 그러다가 f-string을 책에서 사용하길래, 가볍게 정리를 하고 넘어가고자 한다.

f-string 포매팅은 f와 {}을 이용해서 문자열을 포매팅 하는 것으로 다음과 같이 사용한다.
f'문자열 {변수} 문자열'
한번 사용해보겠다.

for i in range(1,11):
    print(f'{i}번쨰 출력값 {i*2}')

????? 뭐야 훨씬 편하고 좋잖아?????

앞으로 f-string format방식을 주로 사용해야겠다...

profile
Time-Series

0개의 댓글