[Python] 기초 - 함수(심화)

ITmakesmeSoft·2022년 9월 3일
0

PYTHON [BASIC]

목록 보기
7/13

함수는 코드 내부에 Local scope를 생성하며, 그 외의 공간은 global scope로 구분

Python의 범위

  • scope
    • global scope : 코드 어디에서든 참조할 수 있는 공간
    • local scope : 함수가 만든 scope. 함수 내부에서만 참조 가능
  • variable
    • global variable : global scope에 정의된 변수
    • local variable : local scope에 정의된 변수

변수 수명 주기(lifecycle)

  • 변수는 각자 수명주기(lifecycle)가 존재
    • built-in scope : 파이썬이 실행된 이후부터 영원히 유지

    • global scope : 모듈이 호출된 시점 이후 혹은 인터프리터가 끝날 때까지 유지

    • local scope : 함수가 호출될 때 생성되고, 함수가 종료될 때까지 유지

      def func():
          a = 20  # local scope에만 존재하는 변수 a
          print('local', a) # local 20
      
      func()
      print('global', a) # NameError: name 'a' is not defined

이름 검색 규칙(Name Resolution)

파이썬 스코프
)

  • 파이썬에서 사용되는 이름(식별자)들은 이름공간(namespace)에 저장되어 있음
  • 아래와 같은 순서로 이름을 찾아나가며, LEGB Rule이라고 부름
    • Local scope : 지역 범위(현재 작업 중인 범위)
    • Enclosed scope : 지역 범위 한 단계 위 범위
    • Global scope : 최상단에 위치한 범위
    • Built-in scope : 모든 것을 담고 있는 범위 (정의하지 않고 사용할 수 있는 모든 것)
      • ex) print()
📢 **함수 내에서는 바깥 Scope의 변수에 접근 가능하나 수정은 할 수 없음.** 단, 상위 scope에 있는 변수를 수정하고 싶다면, `global`, `nonlocal` 활용시 가능
a = 0
b = 1
def enclosed():
    a = 10
    c = 3
    def local(c):
        print(a, b, c) # 10 1 300
    local(300)
    print(a, b, c) # 10 1 3
enclosed()
print(a, b) # 0 1

global 문

현재 코드 블록 전체에 적용되며, 나열된 식별자(이름)가 global variable임을 나타냄

  • global에 나열된 이름은 같은 코드 블록에서 global 앞에 등장할 수 없음
  • global에 나열된 이름은 parameter, for 루프 대상, 클래스/함수 정의 등으로 정의되지 않아야 함
a = 10
def func()
    global a
    a = 3
print(a) # 10
func()
print(a) # 3
  • global 관련 주의사항
    # 1. global에 나열된 이름은 같은 코드 블록에서 global 앞에 등장할 수 없음.
    a = 10
    def func():
        print(a) # global a 선언 전에 사용
        global a
        a = 3
    print(3)
    func()
    print(a)
    # SyntaxError: name 'a' is used prior to global declaration
    
    # 2. global에 나열된 이름은 parameter, for 루프 대상, 클래스/함수 정의 등으로 
    #    정의되지 않아야 함
    b = 10
    def func1(b)
        global b # parameter에 global 사용 불가
        b = 3
    print(b)
    func1(b)
    print(b)
    # SyntaxError: name 'b' is parameter and global

nonlocal 문

  • global을 제외하고 가장 가까운 (둘러 싸고 있는) scope의 변수를 연결하도록 함
    • nonlocal에 나열된 이름은 같은 코드 블록에서 nonlocal 앞에 등장할 수 없음
    • nonlocal에 나열된 이름은 parameter, for 루프 대상, 클래스/함수 정의 등으로 정의되지 않아야 함
  • global과 달리 이미 존재하는 이름과의 연결만 가능
x = 0
def func1():
    x = 1
    def func2():
        nonlocal x  # enclosed scope(func1)의 변수 x에 영향
        x = 2       # enclosed scope(func1)의 변수 x를 2로 변경
    func2()
    print(x) # 2
func1()
print(x) # 0

global, nonlocal 비교

# 선언된 적 없는 변수의 활용
def func():
    global out
    out = 3
func()
print(out) # 3
# 선언된 적 없는 변수의 활용
def func1():
    def func2():
        nonlocal y
        y = 2
    func2()
    print(y)
func1()
''' 
SyntaxError: no binding for 
nonlocal 'y' found
'''
📢 `nonlocal`은 이름 공간상에 존재하는 변수만 가능

함수의 범위 주의

  • 기본적으로 함수에서 선언된 변수는 Local scope에 생성, 함수 종료 시 사라짐
  • 해당 scope에 변수가 없는 경우, LEGB 룰에 따라 이름을 검색함
    • 변수에 접근은 가능하나, 수정은 불가능.
      이는, 값을 할당하는 경우 해당 scope의 이름공간에 새롭게 생성되기 때문
    • 함수 내에서 필요한 상위 scope 변수는 되도록 arument로 넘겨서 활용할 것.
  • 상위 scope에 있는 변수를 수정하고 싶다면, global, nonlocal 키워드 사용
    • 단, 코드가 길어질 수록 변수의 추적이 어렵고, 예기치 못한 오류 발생 가능
    • 가급적 사용하지 않는 것을 권장, 함수로 값을 바꾸고자 한다면 항상 argument로 넘기고 return 값을 사용하는 것을 추천
profile
💎 Daniel LEE | SSAFY 8th

0개의 댓글