TIL (2020.05.28)

Awesome·2020년 5월 28일
0

TIL

목록 보기
4/46

Python

Import statement

파이썬에서 코드를 작성하기 이전에 작업에 필요한 모듈이나 패키지를 불러오기 위해서 import 구문을 사용한다.

파이썬 인터프리터는 어떻게 해당 모듈 혹은 패키지를 찾아오는 것일까?

Import 구문을 실행하였을 때, 파이썬에서 모듈과 패키지를 찾는 순서가 정해져 있다.

  1. sys.modules
  2. built-in modules
  3. sys.path

각각에 대해서 알아보자.

1. sys.modules

docs를 보면 이미 불러온 모듈이나 패키지를 딕셔너리 형태로 저장한다고 되어있다. 즉, 모듈/패키지를 import 할 때 가장 먼저 확인하는 것은 이미 불러온 것인지를 보는 것이다.

sys.modules에 전에 불러왔던 모듈/패키지를 저장해놓기 때문에, 다시 불러올 때 로딩 시간을 단축할 수 있다. 다만, 당연히 새롭게 import 하는 경우에는 해당 딕셔너리에 저장되어 있지 않다.

2. built-in modules

파이썬에서 제공하는 파이썬 공식 라이브러리들이다. 파이썬 안에 포함되어 있으므로 바로 찾아낼 수 있다.

import sys
print(sys.builtin_module_names)

위와 같이 sys.builtin_module_names 를 출력하면 어떤 모듈이 파이썬에 내장되어 있는지 확인할 수 있다.

해당 builtin_module_names를 프린트하기 위해 import 한 sys 모듈도 파이썬의 built-in module 에 포함된다.

3. sys.path

마지막으로 sys.path에 있는 경로들을 확인한다.

import sys
print(sys.path)


sys.path를 출력해보면 리스트 형태로 나타난다. 첫번째부터 순서대로 해당 디렉토리를 확인한다. sys.path는 string 혹은 bytes 타입으로 추가할 수 있다.
주로 local 에서 직접 작성한 모듈을 불러오기 위해 해당 모듈이 위치한 경로를 sys.path에 추가하는 방식으로 이용한다.

위의 sys.modules, built-in modules, sys.path 를 찾아보고 없는 경우에는 에러를 리턴한다.

  • 그럼 sys 모듈은 어찌 찾는가?

    : 위에서 봤듯이 sys 모듈은 built-in module 이므로 경로에 대한 문제가 발생하지 않는다.

sys.path 경로와 관련하여 하나 더 짚고 넘어갈 것이 있다.

Absolute path and Relative path(절대경로와 상대경로)

경로를 지정하는 방식은 크게 절대경로상대경로로 나뉜다.

절대경로는 말그대로 절대적이다. 원하는 모듈이나 패키지의 경로를 절대경로로 지정해주면 어떤 스크립트에서든 문제없이 import 할 수 있다. 경로를 최상단 디렉토리를 기준으로 지정한다.

반면 상대경로현재 import 하는 스크립트를 기준으로 상대적인 경로를 지정한다. 따라서 절대경로에 비해 상대적으로 경로의 길이가 짧게 표현된다는 장점이 있다. 반면 스크립트에 따라서 경로가 바뀐다는 단점도 있다.

아래의 예시를 통해 살펴보자.

my_app 이라는 이름의 최상단 프로젝트 디렉토리가 있다.

  • 만약 package2 의 module3.py 에 정의된 함수 func1 과
  • package2 의 subpackage1 하위 module5.py

를 import 한다고 가정하자.
현재 코드를 실행하는 스크립트는 package2 의 module4.py 이다.

# package2/module4.py

# 절대경로

from module3 import func1
from subpackage1 import module5

# 상대경로

from .module3 import func1
from .subpackage import module5

상대경로가 절대경로보다 짧고 간단하게 표현된다. 최상위 my_app 프로젝트 디렉토리와 하위 package2는 현재 스크립트를 실행하는 module4.py 의 current directory 로 sys.path 에 default로 포함되므로 굳이 지정해줄 필요가 없다. 절대경로는 바로 이 current directory에서 시작한다.

경로의 복잡도, 코드의 가독성 혹은 파일의 위치가 자주 변화하는가 등을 판단하여 절대경로를 지정할 것인지 상대경로를 지정할 것인지 판단해야 한다.


그 밖에 알게 된 것들

closure : 부모 함수 안에 포함된 자식함수

  • closure 안의 변수는 외부에서 접근 불가함
  • 최종 부모함수의 리턴 값은 closure 함수명임
    ex) return closure
  • 함수 호출방법:
    변수 = 부모함수()
    변수(파라미터) : closure를 호출하는 파라미터임

decorator: 함수를 꾸며주는 역할을 함

  • 인자를 함수로 받음
  • decorator 기본형
def decorator(func):
    def wrapper():
        실행문
        return 결과
    return wrapper
@decorator()
def func():
    실행문
  • decorator가 parameter를 받는 경우:
def decorator(parameter):
    def real_decorator(func):
        def wrapper():
            실행문
            return 결과
        return wrapper
    return real_decorator
@decorator(parameter)
def func():
	실행문
  • func 의 parameter가 있는 경우 :
def decorator(func):
    def wrapper(*args, **kargs):
        실행문
        return 결과
    return wrapper
@decorator
def func(a,b):
	실행문
  • class로 decorator 만들기
class Trace:
    def __init__(self,x):  # decorator 에 parameter 있는 경우
        self.x = x         # parameter 없는 경우는 함수로 받음
    
    def __call__(self,func):  # decorator에 parameter 없는 경우에는 실행 함수의 인자를 받음
        def wrapper(*args,**kargs):
            실행문
            return 결과
        return wrapper
        
@Trace(x)
def func(a,b):
    실행문
    return 결과

scope : 변수나 함수, 객체가 유효한 범위
local < enclosing < module < built-in

  • local scope : 주로 함수 안에서 선언된 변수 혹은 함수
  • enclosing scope : 중첩함수가 있을 때 부모 함수에서 선언된 변수
  • global scope : 함수 밖에서 선언된 변수나 함수
  • built-in scope : 파이썬에서 제공하는 내장함수 혹은 속성
  • 변수나 함수의 정의를 찾는 순서
    • local => enclosing => global => built-in
  • 동일한 이름의 변수가 서로 다른 범위에서 선언되면 위의 순서로 변수를 가리는 shadowing 효과가 나타남

class

  • class의 실체는 instance 이며, 각각은 object임
  • class를 실체화 할때 __init__ 메소드가 자동으로 호출됨
  • self 파라미터는 객체 자신을 가리킴
  • class 전체 속성을 사용할 때는 class명.속성 으로 사용

모듈과 패키지

  • 모듈은 하나의 .py 파일
  • 패키지는 여러 모듈을 모아 놓은 디렉토리

패키지 초기화

  • __init__.py 로 패키지 초기 설정 가능함
  • 패키지 import할때 __init__.py 자동 실행됨
  • __init__.py 역할
  1. import 경로 단축
import pkg.mod1
pkg.mod1.func2()

이 경우, __init__.py 에서 먼저 import 해 놓으면 함수명만 불러올 수 있음

# __init__.py
from .mod1 import func2
# main.py
from pkg import func2
fun2()
  1. import 할 수 있는 함수/변수/클래스를 제한할 수 있음
# __init__.py
from .mod1 import fun2
from .mod2 import fun3
__all__ = [“func2”,”func3”]  #__all__ 의 default는 모든 변수임
# main.py
from pkg import *
func2()
func3()
func4() # error
profile
keep calm and carry on

0개의 댓글