새소식

인기 검색어

개발일기

Python default param 평가 시점과 내 생각

  • -

개요

어제 코딩하다가 값을 잘못 심어서 버그를 만들었다. 덕분에 값이 이상하게 들어가고 있는데 어디서 들어가고 있는지 몰라서 좀 헤맨게 있는데 그걸 좀 풀어볼까 한다.

 

바로 default param에 함수 호출을 집어넣었더니, 호출할 때마다 같은 값을 반환하는 것이었다

abc()를 호출할 때마다 같은 값을 반환한다

 

이것과 관련해서 (원리를 잘 설명한 건 아니지만) 꽤 잘 설명한 케이스가 있는데 궁금하면 읽어보는 게 좋다

https://docs.python-guide.org/writing/gotchas/

 

Common Gotchas — The Hitchhiker's Guide to Python

 

docs.python-guide.org

 

아무튼 저렇게 같은 값을 반환하는 이유는, default param에 들어가는 값은 함수 정의시 평가되기 때문이다. 즉, 저 함수가 실행될 때마다 date.datetime.now()를 호출하는 것이 아니라, 이미 함수 정의하는 시점에 datetime.datetime.now()가 호출되어 반환된 값이 쓰여져 있고, 그 값을 가져다 쓰는 걸로 보인다

 

내가 겪어온 언어들에서는 이렇게 동작 안 하던데... 예를 들면 JS에선 이렇게 찍히고 있다

 

 

내 생각에 이렇게 설계된 원인은 Python 언어가 가지는 class 설계 철학 때문에 그런 걸로 보인다.

 

Python은 다른 언어들과 달리 class 선언할 때 클래스 바디에 인스턴스 변수에 대해서 선언하지 않는다. 클래스 바디에 들어갈 수 있는 것은 클래스에서 호출될 수 있는 네임스페이스들이다. 즉, 클래스 변수, 메서드 같은 것들이다

 

클래스와 인스턴스 선언 영역을 엄격하게 분리한다고 생각하면 된다

 

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind                  # shared by all dogs
'canine'
>>> e.kind                  # shared by all dogs
'canine'
>>> d.name                  # unique to d
'Fido'
>>> e.name                  # unique to e
'Buddy'

 

따라서 내 생각에 default param의 원리도 클래스에 private으로 값을 써놓고 메서드가 호출될 떄마다 메서드로 kwarg가 넘어오면 덮어쓰고 아니면 클래스 변수에 있는 값을 갖다 쓰는 것은 아닐까 생각하고 있다

 

그래서 이런 걸 어떻게 막을 수 있을까? 보통은 default에 None을 넣어놓고 메서드 내부에서 값이 없으면 default 값을 덮어쓰는 식으로 동작시킨다고 한다. 특히 default로 []를 넘기면 취약점이 될 수 있어 위험하다고 한다

 

출처: https://docs.python-guide.org/writing/gotchas/

아니면 now = datetime.datetime.now로 넘겨놓고 메서드 내부에서 now()를 호출한다던가 하는 식으로도 할 수 있을 것 같긴 한데... 이게 좋은 방법인지는 잘 모르겠다

 

참조

- 전문가를 위한 파이썬 프로그래밍

- https://docs.python-guide.org/writing/gotchas/

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.