[Python] build-in 함수 overwrite 문제 Develop Tip

최근에는 파이썬을 오래 접하지 못했던 분들의 코드를 보고는 하는데,
C 등의 컴파일러 언어에 익수한 개발자 분들이 범하기 쉬운 오류 패턴들이
있어 별도로 정리를 시작해 볼까 합니다.

다음은 그 중에 하나 입니다.

빌트인 함수를 변수로 전용하며 발생하는 문제!


우선 파이썬 코드에서

>>> max ([3,1,2])
3
과 같이 결과가 잘 나옵니다.
그런데 
>>> max = 3
이라고 명령을 주었는데도 이상 없습니다.

C를 하셨던 분들이라면,

max = 3
이라는 곳에서 벌써 컴파일 오류가 발생했을 터인데 
파이썬은 전혀 그렇지 않습니다.
함수를 포함한 모든 클래스, 변수 등은 단지 글로벌인가 로컬인가의 차이를 두고
서로 서로 덮어 쓸 수 있기 때문입니다.
파이썬 2.x 에서 gevent 를 사용할 수 있는 것도 실은 이와같은 기본 함수를
덮어써서 그 기능을 제대로 한다고 볼 수 있습니다.

이렇게 만든 것이야 바로 어찌보면 파이썬의 자유도를 극대화 시킨 것인데
C와 같은 프로그램을 하던 분들에게는 오류를 발생시키는 원인이 될 수 있습니다.

제대로 테스트를 하지 않는다면, 나중에 실행할 때 예외 처리가 되겠지요.

아래 코드를 한번씩 참고해 보시기를 바랍니다.

#!/usr/bin/env python
#coding=utf8

##########################################################################################
import traceback

##########################################################################################
def builtin_function_ok():
i = 1
j = 2
print max(i, j) # i,j 가 패러미터인데 내부에서는 튜플로 인지하고 모두 돌면서 그 안에서 max
##########################################################################################
def builtin_function_overwrite_problem():
i = 1
j = 2
print max(i, j) # 문제는 하단에서 준 max가 이미 컴파일에 의해 덮어쓴 상황이므로 이 부분에서 예외발생!!! (현재 함수에서만)
print min(i, j)
max = 999 # 파이썬은 이렇게 built-in 함수조차도 변수로 사용가능하게 하는 관대함을 줍니다
print max(i, j) # 변수로 바뀐 max를 다시 함수처럼 사용하려고 하였으니 오류 발생

##########################################################################################
def buildin_type_ok():
t = (3,1,2,'4')
print t
l = list(t) # read-only 튜플을 리스트로 변환
print l

##########################################################################################
def buildin_type_overwirte_problem():
t = (3,1,2,'4')
print t
l = list(t) # 하단에서 overwrite 시킨 list 가 이 부분에서 문제 발생시킴 (현 함수 SCOPE에서만 발생)
print l
list = [2,3,4,5]
print list
l2 = list(t)
print l

##########################################################################################
if __name__ == '__main__':
fns = (builtin_function_ok, builtin_function_overwrite_problem,
buildin_type_overwirte_problem,
buildin_type_ok,
)
for fn in fns:
try:
fn()
except Exception as e:
print "Main Error: %s" % str(e)
print traceback.format_exc()


위 프로그램을 돌리면,

2
Main Error: local variable 'max' referenced before assignment
Traceback (most recent call last):
  File "/Users/mcchae/hostFS/test/Error/overwrite_error.py", line 47, in <module>
    fn()
  File "/Users/mcchae/hostFS/test/Error/overwrite_error.py", line 16, in builtin_function_overwrite_problem
    print max(i, j) # 문제는 하단에서 준 max가 이미 컴파일에 의해 덮어쓴 상황이므로 이 부분에서 예외발생!!! (현재 함수에서만)
UnboundLocalError: local variable 'max' referenced before assignment

(3, 1, 2, '4')
Main Error: local variable 'list' referenced before assignment
Traceback (most recent call last):
  File "/Users/mcchae/hostFS/test/Error/overwrite_error.py", line 47, in <module>
    fn()
  File "/Users/mcchae/hostFS/test/Error/overwrite_error.py", line 32, in buildin_type_overwirte_problem
    l = list(t) # 하단에서 overwrite 시킨 list 가 이 부분에서 문제 발생시킴 (현 함수 SCOPE에서만 발생)
UnboundLocalError: local variable 'list' referenced before assignment

(3, 1, 2, '4')
[3, 1, 2, '4']


와 같이 동작합니다.


어느 분께는 도움이 되셨기를...








덧글

댓글 입력 영역

구글애드텍스트