라벨이 파이썬인 게시물 표시

Python 함수의 기본값은 상수 혹은 None이어야 한다

파이썬에서 함수 선언부는 런타임에 한 번만 실행된다. 따라서 함수에 기본값을 넣을 때는 주의해야 한다.  (그냥 반드시 상수를 넣자고 생각하는 게 맘 편하고, 오류가 더 적을 것 같다) 문제 있는 코드 1) from datetime import datetime def log (msg , dt=datetime.now()): print ( "{}: {}" .format(dt , msg)) def는 한 번 실행되고 그 이후엔 메모리에 상주하기 때문에 이 때 dt는 항상 같은 값(log 함수가 만들어진 시점의 time)만 출력된다. 따라서 아래와 같이 변해야한다. 개선 된 코드 1) def log2 (msg , dt= None ): dt = dt or datetime.now() print ( "{}: {}" .format(dt , msg)) 기본값은 None을 가리킨다. 함수 실행시 keyword argument로 dt값이 있으면 dt값을 쓰고 dt값이 없으면 datetime.now()를 호출한다. 다음으로는 Mutable한 객체가 함수의 기본값일 때 생기는 문제이다. 문제 있는 코드 2) my_list = [ 1 , 2 , 3 ] def log3 (msg=my_list): print (msg) 이 경우엔 my_list의 refence가 넘어가는거라 my_list가 변경이 되면 msg의 기본값도 변하게 된다. 예를들어 그냥 log2()를 실행하면 [1,2,3]을 출력하지만 my_list.append(4)를 실행한 후에 log2()를 실행하면 [1,2,3,4]가 출력된다. 이는 기본 값이 Mutable한 객체이기 때문에 발생하는 문제다. 개선 된 코드 2) 따라서 [1,2,3]을 출력하고 싶으면 아래와 같이 하거나 def log3 (msg=[ 1 , 2 , 3 ]): print (msg) 혹은 Immu...

Python 코드최적화 1. Peephole optimization

파이썬은 인터프리터 언어이지만 컴파일을 거친다. 개발자가 실행한 코드는 한 줄 한 줄 런타임에 컴파일 되고 해석된다. 미리 컴파일 되지 않으면 매 번 소스코드 한 줄을 해석할 때마다 같은 연산을 반복해야할 수 있고, 만약 어떤 연산을 하는 코드가 반복적으로 있다면 해당 코드를 실행할 때마다 연산을 다시해야하기 때문에 느려지게 될 것이다. 따라서 파이썬은 컴파일 할 때 특정 조건에 만족하는 항목들은 미리 계산(pre-calculate) 해두고 이를 상수로 갖고 있는다. 조건은 크게 얘기하면 Immutable한 객체의 연산 이라고 할 수 있고 조금 더 디테일 하게 들어가면 아래와 같다. 1) Numeric Calculation (숫자 계산) Ex) 24 * 60, 300 * 12, 30000* 12000 2) 연산결과의 length가 20이 넘지 않는 Immutable 객체의 Sequence 연산 Yes) "Hello" + "World"       "abc" * 5        (1,2) * 5 No) " ab"*11 (이건 22글자가 되기 때문에 탈락)       (1,2) * 11 (마찬가지로 22개가 되기 때문에 탈락) def my_func (): a = 3000000 * 12000 / 27 b = ( 1 , 2 ) * 5 c = "abc" d = "ab" * 11 e = "the quick brown fox" * 5 f = [ "a" , "b" ] * 3 g = [ "a" , "a" , "a" , "a" , "a" , "a" , "a" , "a" , "a...

파이썬의 First-Citizen(일급시민), Closure, Decorator

1. First-Citizen 정의 : First-Citizen은 특정 자료형을 의미하는 것이 아니고 위 3가지 조건을 만족하면 First-Citizen이다. First-Citizen의 조건 - 변수나 데이터에 할당할 수 있다. - 객체의 인자로 전달할 수 있다. - 객체의 리턴값으로 리턴할 수 있다. function_name / function_name() 에 대한 차이를 먼저 알아야 함. 파이썬에서는 함수도 일급시민이 될 수 있다. 예를들어 아래 코드를 보자. def some_func(number): def square(): print(number * number) return square some_func(4)를 호출하면 square 함수를 반환한다. square 함수의 실행 결과값이 아니라 함수를 반환한다. 2. Closure (먼저 일급시민에 대한 이해가 필요하다) 정의 : 외부 함수의 실행이 종료된 후에도, 내부 함수가 local scope내의 변수(외부함수에서 정해진 변수라던가)를 기억하고 접근할 수 있는 경우를 의미. * 쉽게 말해 외부함수에 의해 환경이 설정 된 내부 함수를 의미한다. Closure is an inner function that remembers and has access to variables in the local scope in which it was created even after the outer function has finished executing. Closure closes over the free variables from their environment. 예를들어, 아래와 같은 함수가 있을 때 def outer_func(msg): message = msg def inner_func(): print(message) return inner_func hi_func = outer_func("Hi") hello_func = outer_...