본문 바로가기
코딩 연습/코딩배우기

파이썬 실천 기술 #05 - 이름공간, 스코프

by good4me 2021. 6. 3.

goodthings4me.tistory.com

 

효율적 개발로 이끄는 파이썬 실천 기술 - 이름공간(namespace), 스코프

(참고용으로 사용할 부분만 간략하게 정리)

이름공간(namespace)

  • 이름과 객체의 매핑, 특정한 하나의 이름이 통용될 수 있는 범위
  • 이름공간이 다르면 같은 이름이 다른 객체를 참조할 수 있다
  • 이름공간의 종류 : 전역 이름공간(모듈별), 지역 이름공간(함수 및 메서드별), 빌트인 이름공간(내장함수, True/False, None 등)
  • 이름공간 생성 시점 : 내장객체 이름공간은 파이썬 실행 시, 모듈별 전역 이름공간은 해당 모듈이 최초에 로딩될 시, 로컬 이름공간은 변수 호출 시 생성되며, 함수에서 벗어나면 그 이름공간은 삭제됨
  • 클래스 정의 시 로컬 이름공간이 생성되고, 클래스 변수와 메서드는 이 이름공간에 속하고, 만들어진 클래스 객체는 이 이름공간을 참조함

 

스코프(scope)

  • 점(.)을 붙이지 않고 변수명만을 지정해 호출하면 파이썬은 직접 접근할 수 있는 이름공간부터 해당 이름을 가진 객체를 검색하는데, 직접 접근 가능한 영역을 스코프라고 함
  • 스코프는 텍스트 상에서의 영역이며, 코드를 작성한 단계에서 정적으로 결정됨
  • 종류(좁은 순) : 로컬 스코프, 인클로징 스코프(nested), 전역 스코프, 빌트인 스코프
  • 이름 검색은 좁은 스코프에서 넓은 스코프 순으로 하며, 가장 먼저 발견한 이름의 객체를 참조하고, 마지막까지 발견 못하면 NameError 예외 발생함
# 로컬 스코프 - 함수(메서드 포함) 내로 제한, 함수 내 변수(로컬변수)의 참조 범위

def f(v):
    print(v)  # 함수의 인수도 로컬 스코프
    v = f'f_function'
    print(v)
    print(locals())  # 내장함수 locals() : 로컬 변수 목록 얻음

f(20)

# 컴프리헨션도 로컬 스코프
c = [value for value in range(1)]
print(c)
#print(value)  # NameError: name 'value' is not defined

# 모듈의 최상위 레벨에서 내장함수 locals()는 전역 스코프와 일치


[결과]
20
f_function
{'v': 'f_function'}
[0]

good4me.co.kr

# 전역 스코프 - 모듈의 최상위 레벨 스코프 의미 (이 스코프에서 정의되어 있는 변수는 전역 변수)
# 다른 모듈에서 정의한 값은 참조 시 명시적 임포트 필요(스코프가 다르므로) 
# 함수나 클래스, 메서드는 반드시 모듈 내부에 정의함 => 같은 모듈 내에서는 항상 모듈의 전역변수 참조 가능

x = 100
def f():
    print(x)  # 전역 변수 참조
f()

def g():
    x = f'f_function'  # 지역 변수
    print(x)
g()
print(x)

# 함수 내에서 전역변수 참조 후 그 함수 내에 같은 이름의 로컬변수 정의 불가 (전역변수 덮어쓰기 방지)
def fn():
    print(x)
    #x = f'fn_function'  # UnboundLocalError: local variable 'x' referenced before assignment

fn()

# 전역 변수 덮어쓰기
x = 100
def fg():
    global x  # 전역변수임을 명시 후 업데이트 함
    x = '200'
    print(x)  
fg()
print(x)  # 전역변수 값 업데이트됨

[결과]
100
f_function
100
100
200
200

 

# 전역변수가 컨테이너 객체이고 그 컨테이너 객체가 유지하는 값을 덮어쓸 때는 global 문이 필요없음(참조 수행 후 값 업데이트)
# x[0] = 2 에서 객체 'x' 먼저 검색 후 객체의 인덱스 0의 값 업데이트 함
x = [0, 1]
def f():
    x[0] = 2

print(x)
f()
print(x)

# 전역변수 치환 기능은 가독성 및 유지보수성 저하 원인(사용 시 주의)


[결과]
[0, 1]
[2, 1]

 

# 빌트 인 스코프 - 내장 객체의 스코프이고, 가장 마지막에 검색되는 스코프
# 이 스코프에 있는 내장 객체는 builtins 모듈에 정의되어 있고, 
# 전역변수 __builtins__로 이 모듈에 대한 참조를 얻을 수 있음

#print(dir(__builtins__))
cnt = 1
for i in dir(__builtins__):
    print(i, end=', ')
    cnt += 1
    if cnt % 7 == 0:
        print()


[결과]
ArithmeticError, AssertionError, AttributeError, BaseException, BlockingIOError, BrokenPipeError, 
BufferError, BytesWarning, ChildProcessError, ConnectionAbortedError, ConnectionError, ConnectionRefusedError, ConnectionResetError, 
DeprecationWarning, EOFError, Ellipsis, EnvironmentError, Exception, False, FileExistsError, 
FileNotFoundError, FloatingPointError, FutureWarning, GeneratorExit, IOError, ImportError, ImportWarning, 
IndentationError, IndexError, InterruptedError, IsADirectoryError, KeyError, KeyboardInterrupt, LookupError, 
MemoryError, ModuleNotFoundError, NameError, None, NotADirectoryError, NotImplemented, NotImplementedError, 
OSError, OverflowError, PendingDeprecationWarning, PermissionError, ProcessLookupError, RecursionError, ReferenceError, 
ResourceWarning, RuntimeError, RuntimeWarning, StopAsyncIteration, StopIteration, SyntaxError, SyntaxWarning, 
SystemError, SystemExit, TabError, TimeoutError, True, TypeError, UnboundLocalError, 
UnicodeDecodeError, UnicodeEncodeError, UnicodeError, UnicodeTranslateError, UnicodeWarning, UserWarning, ValueError, 
Warning, ZeroDivisionError, __IPYTHON__, __build_class__, __debug__, __doc__, __import__, 
__loader__, __name__, __package__, __spec__, abs, all, any, 
ascii, bin, bool, breakpoint, bytearray, bytes, callable, 
chr, classmethod, compile, complex, copyright, credits, delattr, 
dict, dir, display, divmod, dreload, enumerate, eval, 
exec, execfile, filter, float, format, frozenset, get_ipython, 
getattr, globals, hasattr, hash, help, hex, id, 
input, int, isinstance, issubclass, iter, len, license, 
list, locals, map, max, memoryview, min, next, 
object, oct, open, ord, pow, print, property, 
range, repr, reversed, round, runfile, set, setattr, 
slice, sorted, staticmethod, str, sum, super, tuple, 
type, vars, zip, 

 

# 클로저(closure) - 작성 시 환경을 기억하는 함수 객체의 한 종류
# 즉, 자신이 만들어졌을 때의 환경(바깥쪽 스코프)에 있는 변수에 대한 참조 유지

def counter():
    count = 0

    def _increment():
        nonlocal count
        count += 1
        return count
    return _increment  # 함수 객체 반환

# 함수 안의 로컬변수는 마지막 실행 시점에서 사라지지만, 
# 클로저 함수 객체는 자신이 정의된 시점에 바깥쪽 스코프에 정의되어 있던 변수(count)에 대한 참조를 계속 유지함
# 즉, _increment() 함수 실행 시마다 로컬 변수 count 값이 증가함

cnt1 = counter()
print(cnt1)  # function counter.<locals>._increment at... 
print(cnt1())
print(cnt1())


[결과]
<function counter.<locals>._increment at 0x7f0056a0c440>
1
2

 

[참고/출처] 효율적 개발로 이끄는 파이썬 실천 기술 - 파이썬에 숨겨진 힘을 이용해 개발 효율을 높이자!

 

댓글