2-1. 필수 문법 ( 변수 유효범위 )

uoayop·2021년 3월 14일
0

Leaf와 Python

목록 보기
5/21
post-thumbnail

단순히 복사 + 붙여넣기로 한 작업과, 파이썬의 구조와 특징을 정확하게 안 후에 성능집약적으로 코딩을 한 작업은 확연히 다르다.

구조를 알아야만 리팩토링이 가능하기 때문이다. 코드의 깔끔함과 유지보수성은.. 반드시 고려해야 한다.

그럼 개발자를 위한 개발을 하기 위해 알아야하는 필수 문법들을 알아보자

Variable Scope

  • 오늘의 키워드
    • scope, global, nonlocal, locals, globals

scope

변수의 유효범위를 의미한다.

  1. 지역 스코프에서 전역 변수를 읽을 수 있다. (🥕)
a = 10 # global variable

def foo():
    # read global variable
    # 지역 스코프에서 전역 변수를 읽을 수 있다.
    print('ex 1>', a)

foo()

# read global variable
print('ex 1>', a)
  1. 파이썬에서 변수를 찾을 땐, 로컬 스코프에서 먼저 찾는다.
b = 20

def bar():
    # bar 함수 내부의 로컬 스코프에서 먼저 b 변수를 찾아서 30을 할당해준 뒤에
    # 바깥 쪽에 있는 b 변수는 20은 다시 할당이 된 변수값이다.

    b = 30 #local variable
    print('ex 2_ fuction scope>', b) # read local variable _ first

bar()
print('ex 2_global_scope>', b) #read global variable _ second

# 전역에 있는 변수를 찾을 땐, 전역 스코프에서만 찾는다.
# 없으면 예외가 발생한다.
  1. 전역 변수를 로컬 스코프에서 수정할 수 없다.

c = 40

def foobar():
    # 아래의 세 코드 모두 동작하지 않는다.
    #c = c + 10
    # c = 10
    # c += 100
    print('ex 3>',c)

foobar()

# UnboundLocalError: 로컬 변수 c가 할당 전에 참조 되었다는 에러가 발생한다.
# 전역에 있는 값을 지역에서 특정한 예약어 없이는 수정할 수 없다.
# 이때 사용하는 예약어가 ✨global 이다.

global

전역 변수를 지역 스코프에서 수정하기 위해 사용하는 예약어다.

d = 30

def barfoo():
    global d
    d = 40
    d += 100
    print('ex 4>',d)

barfoo()
print('ex 4>',d)

# 전역 스코프에 선언된 변수는 global이라는 예약어를 통해서 읽고 쓸 수 있다.

global 사용 시 주의하자

  • 클린 코드를 위해선 global 최대한 사용 안하는 것이 좋다.
  • 라인 수가 많을 수록 유지보수가 힘들어질 수 있다.

nonlocal (⭐️중요)

지역 변수가 선언된 스코프 안에 또 하위의 지역 스코프가 있을 때 상위 지역 변수의 값을 접근하기 위해서 nonlocal 예약어를 이용한다.

클로저? 🤔

  • 클로저는 nonlocal을 사용하는 대표적인 예시다.
  • 클로저는 함수를 호출할 때 다시 꺼내서 사용하는 함수다. 즉 함수에서 함수를 리턴한다.
  • 함수가 실행이 끝나도 바깥 쪽 함수 영역에 있는 변수가 소멸되지 않도록 해준다.

JS에서 쓰이는 클로저

  • 독립적인 변수를 가리키는 함수, 클로저 안에 정의된 함수는 만들어진 환경을 ‘기억한다’.
  • 함수 내에서 함수를 정의하고 사용하면 클로저라고 한다. 대개는 정의한 함수는 리턴하고 사용은 바깥 쪽에서 한다.
  • 은닉화가 가능하다.
def outer():
    e = 70 # outer 함수의 지역 변수
    def inner():
        nonlocal e 
        # inner 함수의 지역변수가 아니라 상위의 outer 함수의 지역변수를 가져다 쓴다.
        # nonlocal을 붙이지 않으면 UnboundLocalError 에러가 발생한다.
        
        e += 10 
        print('ex 5>',e)
    return inner # 함수 자체를 반환

in_test = outer() #클로저

in_test() # print: 80 
in_test() # print: 90
# 함수 내부의 변수가 소멸되지 않는다.
  • nonlocal + 클로저를 사용하면 하나의 함수를 이용해서 적은 수의 변수를 이용할 수 있고, 효율적으로 호출해서 운영할 수 있다.
  • 모듈화를 통해 사용하기 쉬워진다.
  • 코테에서도 이런 케이스가 나온 적이 있다고 하니 눈에 익혀두자.

locals

지역스코프에 선언된 객체들을 모두 딕셔너리 형태로 출력해주는 예약어다.

def func(var):
    x = 10
    def printer():
        print('ex 6> printer func inner')
    print('ex 6> func inner',locals()) # 지역변수 전체 출력

func('hi')
ex 6> func inner {'var': 'hi', 'x': 10, 'printer': <function func.<locals>.printer at 0x7f95cf2d25e0>}

globals

전역 스코프에 선언된 모든 객체들이 딕셔너리 형태로 출력되는 예약어다.

print('ex 7 >',globals()) # 전역 변수 전체 출력

# 선언했던 모든 값들이 출력이 된다.
  • globals를 이용해서 아래와 같이 key-value 형태로 변수를 선언할 수도 있다.
test_variable = 100

globals()['test_variable'] = 100
# 변수를 선언할 때 내부적으로 위와 같은 원리로 동작한다.
# globals 함수 호출한 후에 key: value 형태로 변수를 저장해준다.
  • 동적으로 변수를 선언할 수도 있다. 😳
# 변수를 선언할 떄 자동화 할 수 있을까?
# 지역 내부에서 -> 동적으로 전역 변수 생성

for i in range(1,10):
    for k in range(1,10):
        globals()['plus_{}_{}'.format(i,k)] = i+k

print('ex 8 >',plus_5_5)
# 출력 : 10

[출처] 인프런 - 모두를 위한 파이썬 : 필수 문법 배우기 Feat. 오픈소스 패키지 배포 (Inflearn Original)

profile
slow and steady wins the race 🐢

0개의 댓글