Python TIL (20180731)

2019-02-10

.

study program : https://www.fastcampus.co.kr/dev_school_css

# 파이썬은 절차지향, 객체지향, 클로저 모두 지원한다.

# closure

  • 실제로는 거의 안쓰고 oop를 많이 사용하나 oop를 막아두었던 시절에는 울며겨자먹기로 클로저를 이용한다.

  • 클로저의 핵심은 함수 내부에 상태정보를 가지고 있다는 것이다.

  • 클로저는 일반함수와 다르게 입력이 들어가는데 내부에 상태정보같은게 있어서 상태정보에 의해 값이 달라지게 된다. 반면에 일반함수는 오로지 입력값에 의해 결과값이 결정되는 것과는 대조적이다.

  • 클로저는 외부함수와 내부함수가 있고 상태정보를 갖고 있는 것이 특징이다.

  • ex) 간단한 은행계좌 함수를 클로저를 이용해서 만들어보자.

def account(name, money):
    
    def change_money(amount):
        nonlocal money
        money += amount
        return name, money
    
    return change_money
greg_acnt = account('Greg',5000)
mark_acnt = account('Mark',200)
greg_acnt(500)
('Greg', 5500)
mark_acnt(-500)
('Mark', -300)

# 전역변수 vs 지역변수

  • 전역변수 : global variable, 프로그램 내 전체에서 접근할 수 있는 변수

  • 지역변수 : local variable, 특정함수 내에서만 접근할 수 있는 변수

  • 지역변수를 전역변수로 변경하고 싶을때

ex) global a -> 파이썬아 나는 아까 정의했던 전역변수 a를 참조해서 쓸거고 절대 지역변수가 아니야. 라고 명령하는 것

  • 함수와 함수사이에 있는 변수는 글로벌도 아니고 로컬도 아닌경우가 있는데 이를 free variable이라고하고 함수의 함수에서 사용하고 싶은 경우 ‘nonlocal 변수이름’을 통해 참조할 수 있다.

  • 네임스페이스 : 그 함수에서의 변수 국적 (어떤 함수의 국적인가)

# 스텍프레임

  • 프레임 : 함수를 실행하기 위해 변수들을 모아놓은 공간

  • 스텍 : 급식판

  • 사용예시)

a=10

def func(b,c):
    d=b+c
    e=b-c
    return d, e

func(20, 30)
(50, -10)

step1) 최초에 글로벌 프레임이 만들어져서 메모리 가장 밑에 쌓이게 되고 거기에는 a=10과 func 함수에 대한 내용이 저장된다.

step2) func 함수를 호출하게 되는 순간(func(20,30)이 실행되는 순간) func에 대한 스텍프레임을 만들어져서 글로벌 프레임 위에 쌓이게 된다.

step3) func 스텍프레임 내에는 그 함수에 있는 변수(c,b,d,e 총 4개) 만큼 공간이 생긴다.

step4) 그리고 func 실행시 입력값(20,30)에 따라 각각의 변수에 수들이 저장이 된다.

step5) 일들이 일어나는 동안 메모리에 프레임들이 쌓여있다가. func 함수가 실행이 완료되면서 return 값이 반환되는 순간 func 스텍프레임은 메모리 공간에서 사라지게 된다.

step6) 프로그램이 전부 실행이 완료되면 글로벌 프레임까지 메모리 공간에서 사라지게 된다.

  • 사용예시2)
a=10

def func():
    a=20
    print(a)

func()
print(a)
20
10

step1) 프로그램을 실행하게 되면 최초에 글로벌 프레임이 만들어져서 메모리 가장 밑에 쌓이게 되고 그 글로벌 프레임 안에는 a=10와 func 함수에 대한 내용이 들어가게 된다.

step2) func()를 실행하게 되면 func에 대한 스텍프레임을 만들어지게 되고 메모리공간에서 글로벌 프레임 위에 쌓이게 된다.

step3) 그 스텍 프레임 안에 a=20이 저장되게 된다.

step4) 함수 내에서 프린트를 했다면 a=20이 당연히 출력되게 되고

step5) 함수가 그리고 종료되는 순간 func 스텍프레임이 사라지게 된다.

step6) 그리고 이 상태에서 프린트를 하는 순간 글로벌 a에 있는 a =10이 출력되게 된다.

step7) 프로그램이 종료된다.

  • 사용예시3)
def f(a,b):
    return a+b

def g(c,d):
    e=f(c,d)
    return e

g(10,20) 
30

step1) 프로그램을 실행하게 되면 최초에 글로벌 프레임이 만들어져서 메모리 공간 가장 밑에 쌓이게 되고 그 글로벌 프레임 안에는 프로그램 작성된 순서대로 f, g에 대한 함수 내용이 저장된다.

step2) g(10,20) 이 실행되는 순간 g에 대한 스텍프레임이 만들어져서 글로벌 프레임 위에 쌓이게 되고 그 스텍 프레임 안에는 g의 변수 c =10, d =20, e = ‘아직 빈공간’ 총 3개의 공간이 만들어져 앞에 세가지 정보가 저장되게 된다.

step3) 그리고 함수 f(c,d)가 실행되면서 f에 대한 스텍프레임이 만들어지면서 g 스텍 프레임 위에 쌓이게 된다. 그리고 그 안에는 a,b 공간이 만들어진다. 그리고 c의 값 10, d의 값 20이 복사되어 a,b공간에 저장이 된다.

step4) 그리고 a+b 연산은 별도의 스텍이 생성되서 그 안에서 실행된다. (참고로 c언어는 별도의 스텍에서 실행되는 것이 아니라 cpu의 레지스터에서 계산을 실행해서 리턴한다) 그리고 그 안에 a값 10, b값 20이 각각 쌓이게 되고 + 연산을 실행되어 10,20은 없어지고 30이 쌓이게 된다. 그리고 30을 e로 리턴해주면서 계산하는 스텍 전체가 사라진다.

step5) 동시에 f의 함수 실행이 끝나면서 f의 스텍프레임이 사라진다.

step6) 그리고 g의 함수에서 e의 값에 30이 쌓이는 순간 e를 리턴해주면서 g의 스텍프레임도 사라지게 된다. 그리고 프로그램 전체 실행이 완료된다.

# packing과 unpacking

  • 아래와 같이 변수를 쪼개는 것을 언패킹이라고 한다.
li = [1,2,3,4]

a, *b = li
print(a)
1
print(b)
[2, 3, 4]
  • 반면에 a = 1,2,3,4의 결과값은 (1,2,3,4)로 튜플이 되는데 이것을 패킹이라고 한다.
a = 1,2,3,4
print(a)
(1, 2, 3, 4)

# 가변인자 설정

예를 들어 아래와 같이 *args를 가변인자라고 한다. 정수, 숫자, 문자 다 받을 수 있다.

def func(*args) :

이렇게 하면 인자를 예를 들어 func(*args = 1,2,3,4)가 전달이 되면 튜플로 인자를 함수내로 전달하게 된다.

  • ex)
def func(*args) : 
    s=0
    
    for arg in args:
        s+=arg
    
    return s

result = func(1,2,3,4)
print(result)
10
  • ex2)
li = [1,2,3,4]

def func(*args): 
    print(args)
    
func(li)
([1, 2, 3, 4],)

리스트를 아예 하나의 변수로 취급한다.

위의 예시처럼 리스트에 있는 내용을 풀어서(언패킹해서) 계산하고 싶다면

func(*li) 이렇게 실행하면 된다.

그렇다면 **kwargs(= key argument)는 무엇인가

==> 키 : 벨류로 받아서 함수 내부에는 딕셔너리로 들어간다.

# 데코레이터

  • 함수의 기능을 추가할때 쓴다.

  • 자주 쓰는 기능이다.

# 왜 숫자에 대해 알아야 하나

  • 파이썬을 쓰는 순간 정수는 크게 신경을 쓰지 않아도 된다.

  • 하지만 실수에 대한 개념은 명확히 잡아야 한다.

  • 컴퓨터는 실수를 부정확하게 이해하기 때문이다.

예를 들어 for문으로 0.01을 10번 돌려서 더하면 0.1이 되야 하는데 실제 결과값은 0.10000000007로 나온다.

# 컴퓨터가 숫자를 표현하는 방식

  • 정수 - 양수, 음수,0

  • 컴퓨터는 양수를 0과 1로 표현한다

  • 컴퓨터는 음수를 2의 보수로 표현한다

  • 실수는 컴퓨터가 부동소수점으로 표현한다. 특징은 표현범위는 넚은데 정밀도가 떨어진다.

# 16진수 팁

a =1010

b

c =1100

d

e

f = 1111

# 진수표현 팁

  • 0x 숫자 (16진수라는 거다)

  • 0b 숫자 (2진수라는 거다)