Programming Language/Python

모듈과 __all__

hustle_D 2025. 7. 21. 15:44
반응형

파이썬에서 모듈(module)이란 파이썬 코드(.py 파일)를 하나의 단위로 묶은 파일로서, 다른 파이썬 파일에서 재사용 가능하도록 만든 코드 집합을 의미한다

간단하게 재사용이 가능한 클래스, 함수, 변수등을 담고 있는 파이썬 파일 하나를 모듈이라고 한다.

 

간단하게 산술을 위한 모듈을 하나 만들어보자.

먼저 파이썬 파일을 하나 생성해 주고 

 

사칙 연산에 관련된 함수들을 정의해주자.

이제 모듈을 불러올텐데 모듈을 불러올때의 차이점이 존재한다

 

import module

위와 같이 사용하게 되면 모듈 전체를 불러오나 함수의 사용시에 namespace를 사용해줘야한다

그래서 함수의 사용시에는 아래와 같이 모듈명을 앞에 붙여줘야만 한다.

print(module.add(1, 2))

이렇게 사용하면 네임 충돌에 대한 위험성이 없고 유지보수와 가독성이 높아지는 장점이 있다.

 

여기서 뒤에 as를 사용해주면 

import module as md

네임스페이스를 지정해줄 수 있게 되고 함수를 사용할때 이 네임 스페이스를 사용해서 

print(md.add(1, 2))

모듈을 사용할 수 있게 된다 

 

반면에 

from module import *

위와 같이 사용한다면 모듈 내부에 정의된 모든 공개 대상(__all__)을 현재 스코프로 직접 import 한다

만약 직접 __all__을 설정하지 않았다면 명칭에 _로 시작하지 않은 이름만 import * 대상으로 자동 선택한다.

print(add(1, 2))

그래서 사용할때 위와 같이 모듈명칭을 사용하지 않더라도 바로 사용이 가능하다.

이렇게 사용하면 코드가 짧아지나 어떤 모듈에서 어떤 함수가 들어온건지 추적이 어렵이름 충돌의 위험이 존재하게 된다.

 

또한 * 이 아니라 명칭을 직접 작성해주면 모듈 내부에서 해당 기능만 가져다 사용도 가능하다.

from module import add, div

print(add(1, 2))
print(div(1, 2))

물론 이렇게 사용하면 지정한 기능들만 사용 가능하다.

 

그리고 위 형태에서도 as를 사용해서 별칭을 사용하는 것도 가능하다.

from module import add as ip, div as dp

print(ip(1, 2))
print(dp(3, 1))

 

추가로 위에서나온  __all__는 아직 설정하는 방법을 확인한적이 없기에 __all__에 대해서와 설정 방법에 대해서 확인해보자.

 

__all__

__all__은 파이썬 모듈 내에 정의하는 리스트 형태의 특수한 변수로 from module import * 사용할 때, 외부에 공개할 이름(심볼)을 명시적으로 정의하고 이는 모듈 외부에서 사용할 수 있는 API 범위를 제한하거나 문서화하기 위해서 사용된다.

 

만들었던 모듈의 형태를 보면 

이렇게 구현되어 있을때 어느 위치든 상관없이 (관례적으로는 가장 상단에 위치시키기에 최상단에 위치시키는 것이 좋을듯 하다)

이렇게 명칭을 리스트의 형태로 구현해주면 외부에서 from - import * 을 사용해서 모듈을 import했을때 

이렇게 함수를 모듈명 네임스페이스 없이 사용이 가능해진다.

만약 __all__ 리스트에서 없어지면 

이렇게 확인되지 않은 참조로 에러를 띄운다.

이건 함수에만 국한된게 아니라 변수나 클래스도 동일하다.

__all__이 없는 경우엔 모든 모듈을 다 import 해줘서 모두 사용이 가능하다.

다만 명칭의 가장앞 문자가 _ 언더바인 경우에는 가져오지 않는다.

이렇게 가져오지 않는다.

 

그럼 왜 _를 사용했을때 모듈내에서 가져오지 않게 했을까

 

파이썬에서는 접근 제어 키워드(public, private, protected)가 없기에 대신 이름 규칙을 통해서 비공개를 표현한다.

_언더바의 갯수 및 형태에 따라서 각각 아래의 의미를 가진다.

  • def func : pass - public, 공개로 외부에서 자유롭게 사용이 가능하게 만들어진 형태
  • def _func : pass - 비공개(암시적), 외부에서 사용하지 말라는 암시적인 형태
  • def __func: pass - 클래스 내부 전용: 이름 맹글링(name mangling)이 적용됨
  • def __func__: pass - 특수메서드(__init__, __str__)등, 시스템이 사용하는 예약 이름

여기서 _언더바가 하나인 형태의 경우는 외부에서 접근하려면 접근은 가능하다.

위 처럼 모듈의 형태라면 접근이 불가능하나 아래와 같이 클래스의 내부에 존재하는 경우에는

class A:
    def __init__(self):
        self._secret = 42
a = A()
print(a._secret)  # 접근됨

접근이 가능하다.

이렇게 해둔 이유는 내부 구현용으로 사용되었으니 외부에서 사용하지 말아라 만약 사용한다면 너가 책임져라 라는 의미를 가기 때문이다.

 

추가적으로 __언더바 두개의 형태인 경우는 위에 _언더바 하나와는 다르게 해당 명칭으로 접근이 불가능하다.

class A:
    def __init__(self):
        self.__secret = 99

 

이는 이름 맹글링을 하기 때문인데 여기서 맹글링이란 영어로 mangling으로 이름을 자동으로 변형하는 것을 말하며 내부적으로 파이썬에서는 _클래스명__secret의 형태로 변경 시켜버린다.

그렇게 되면 __secret으로는 접근이 불가능하다.

물론 _클래스명__secret로는 접근이 가능하다.

이걸 통해서 외부에서 쉽게 접근하지 못하도록 한다.

 

실무에서는 __언더바 두개의 형태의 경우는 정말 필요한 상황에서만 사용되고 _언더바 하나의 형태를 많이 사용한다고 한다.

 

 

반응형