python __init__.py 작성 유형

https://towardsdatascience.com/whats-init-for-me-d70a312da583

번역

사용자가 module 사용하는 방법은 package 의 __init__.py 를 사용하는 것.

Modules

작은 modules 로 분리하는 것은 좋다. 첫째로, 모듈은 연관된 소스들이 뭉쳐있다. 둘째, 논리적으로 비슷한 코드가 뭉쳐 있으면 읽기,이해하기가 좋다.

developer 에게 좋은 모듈은 user 에게 좋은 모듈인가? user 는 아필요 없을 것이다. 그 패키지 않에 무엇들이 있는지. 사용자에게는 필요한 모듈만 명시적으로 요청할 수 있어야 한다. 패키지 developer 가 해야 할 것은?

An example package

/src
    /example_pkg
        __init__.py
        foo.py
        bar.py
        baz.py
    setup.py
    README.md
    LICENSE

*.py

# foo.py
def foo_func():
  print('this is foo')

# bar.py
def bar_func():
  print('this is bar')

# baz.py
def baz_func():
  print('this is baz')

Your code as a grocery store

import 문과 패키지 구조에 대해서 문장으로 설명하기 힘들고. package 를 식료품점으로 user 를 쇼핑객으로 생각해보자. developer 는 스토어의 주인이자 관리자이다. 너의 임무는 고객에게 최상의 서비스 제공을 위해 매장을 구성하는 것이다. 너의 __init__.py 파일을 그 구성을 묘사한다. 아래 3가지 방식으로 설명하겠다.

  • 일반 상점
  • 편의점
  • 온라인 상점

일반 상점 (잡화점)

이 가정에서 user 는 모든 상품을 볼 수 있다. import example_pkg. user 의 코드는 package 이름 class, function 을 타이핑 하는 것만으로 모두 사용할 수 있다. 소스 코드에 뭐가 있든 상관 없이. 오래된 잡화점 같다. user 가 문에 들어서면, 매장 주변의 쓰레기통, 선반에 이것저것이 놓여 있다.

Behind the scenes

# __init__.py
from .foo import *
from .bar import *
from .baz import *

User implementation

import example_pkg
example_pkg.foo_func()
example_pkg.bar_func()
example_pkg.baz_func()
장점단점점
user는 모듈 이름을 알 필요 없다. 어떤 기능이 어떤 모듈에 있는지 기억 할 필요 없다. 패키지 이름과 함수 이름만 있으면 된다.
user 는 top-level 패키지가 import 되면 모든 펑션에 접근할 수 있다.
IDE tab 완성으로 example_pkg.<tab> 잡화점 주인장이 모두 알려주는 것과 같다.
새로운 기능이 modules 에 추가되어도 변경을 할 필요가 없다. 자동으로 include 된다. 선반에 그냥 새로운 상품이 추가된다.
모든 함수와 class 이름이 고유해야 한다. 패키지가 크면, 네임스페이스에 많은 것이 추가되고 느려질 수 있다.
일반 상점에는 개발 고객이 원치 않는 잡동사니가 많아 부담스러울 수 있다.
user 가 접근 못하게 하려면 __function_name 등의 노력을 해야 한다.
빗자루나 대걸레 처럼 큰 것은 숨기기 어렵다.
user가 빗자루를 집거나 바닥을 쓸 가능성이 없더라도 developer 는 사용자가 건들지 않기를 원하기에 어떻게든 추가 조치를 해야만 한다.

Recommendations / 언제 쓰는가

  • user의 작업 흐름 예측이 어려울 때, pandas 나 numpy 같이 util 성으로 이것저것 호출될 때. 잡화접의 일반적인 사항
  • user가 여러 모듈 사이를 자주 이동할 때
  • 함수 및 클래스 이름이 매우 설명적이고 기억하기 쉽고 모듈 이름을 지정해도 가독성이 향항되지 않을 때, developer 의 제품이 과일 야채와 같이 친숙한 것이라면 name tag 가 필요 없다.
  • 적은 모듈과 함께 사용, 모듈이 너무 많으면 사용자가 문서에서 원하는 기능을 찾기 어려울 것이다. 너무 커지지 않을 때는 사용할 수 있다. (일본의 돈키호테!)
  • objects 를 자주 추가하거나 제거할 때, 고객을 방해하지 않고 쉽게 추가하고 제거할 수 있다.

편의점

편의점은 일반 잡화점의 변형이다. from .module import * 대신에 from .module import func 방식을 사용한다.

편의점은 잡화점과 많은 특징이 공유된다. 상대적으로 제한된 제품들이 진열됨. 잘 진열되어 있어 상품명 표시를 보지 않도로 한눈에 찾을 수 있다. 잘 정리되어 있고 빈상자가 빗자루는 잘 치워져 있고 판매 제품만 선반에 있다.

Behind the scenes

# __init__.py
from .foo import foo_func
from .bar import bar_func
from .baz import baz_func

User implementation

import example_pkg
example_pkg.foo_func()
example_pkg.bar_func()
example_pkg.baz_func()
장점단점
모든 장점은 잡화점의 것과 같으며 추가로
사용자가 사용할 수 있는 개체를 제어하기가 쉽다.
__init__.py 은 기능이 많은 모듈이 많아지면 복잡해진다. 일반상점과 마찬가지로 어수선한 편의점은 잡화점과 같다.
새로운 기능이 추가되면 __init__.py 에도 명시적으로 추가해야 한다.
최신 IDE 는 누락된 import 감지에 도움이 되지만 잊기 쉽다. 편의점에도 최소한의 상품표가 있다. 선반의 항목을 변경할 때 상품표도 변경해야만 한다.

Recommendations / 언제 쓰는가

  • 모듈이 어느정도 단일 클래스로 구성되어 있을 때 (ex. geopandas.geodataframe import GeoDataFrame)
  • 가벼올 개체 수가 적을 때
  • 사용 개체게 명확한 이름이 있을 때
  • 사용자에게 필요한 개체와 필요하지 않은 개체를 명확히 알 때
  • 새로운 모듈추 추가 되지 않을 것으로 예상 될 때

온라인 잡화점

온라인으로 식료품을 구매한 사람이라면, 누구나 올바른 제품을 주문하는데 고객의 노력이 필요하다는 것을 알고 있다. 사용자는 제품을 검색하고, 브랜드와 원하는 사이즈를 선택해야만 한다. 그러나 이런 과정으로 무제한의 재고실에서 원하는 젶무을 정확하게 구할 수 있다.

파이썬 package 에서, 전체 패키지를 가져오는 편리함을 피하고 어떤 부분이 import 되 있는지 사용자에게 명확하게 하는 것이 현명할 수 있다. 이를 통해 developer 는 user 에게 부담을 주지 않으면서 패키지에 더 많은 부분을 포함할 수 있다.

Behind the scenes

# __init__.py
import example_pkg.foo
import example_pkg.bar
import example_pkg.baz

User implementation

import example_pkg

example_pkg.foo.foo_func()
example_pkg.bar.bar_func()
example_pkg.bar.baz_func()

or 

from example_pkg import foo, bar, baz

foo.foo_func()
bar.bar_func()
baz.baz_func()

or

import example_pkg.foo as ex_foo
import example_pkg.bar as ex_bar
import example_pkg.baz as ex_baz

ex_foo.foo_func()
ex_bar.bar_func()
ex_baz.baz_func()
장점단점
__init__.py 가 단순화된다. 새 모듈이 추가될 때만 업데이트 하면 된다. 온라인 상점 업데이트는 쉽다. 제품 데이터베이스 설정만 변경한다.
flexible 하다. 사용자가 필요한 것만 가져오거나 모든것을 가져오는데 사용할 수 있다. 온라인 상점의 고객은 자신이 원하거나 필요한 것만 검색이 가능하다. 사과가 필요하면 과일상자를 뒤질 필요 없고, 과일상자의 모든것이 필요하면 그것도 가능하다.
앨리어싱으로 긴 package.module 을 정리할 수 있다. 온라인 상점은 복잡하지만 나의 쇼핑 목록을 이용하면 빠른 쇼핑이 가능하다
동일한 이름의 여러 객체를 다룰 수 있다.
foo.foo_func() 는 foo가 어느패키지에서 왔는지 나타나지 않는다.
alias 없이는 매우 긴 코드 덩어리가 만들어 질 수 있음. example_pkg.foo.foo_func()
사용자가 사용가능한 기능을 추적하기 어려움. 온라인 식료품점은 가능한 모든 상품을 보기는 어려움



Recommendations / 언제 쓰는가

  • 복잡한 모듈에 대부분의 기능이 사용자에게 필요하지 않을 때
  • import example_pkg 가 많은 객체를 가져올 때
  • 다양한 종류의 사용자를 위해 매우 명확한 워크플로를 정의할 수 있는 경우에
  • 사용자가 문서를 탐색할 수 있을 것으로 예상할 때 
  • ex) mataploglib, bokeh, scipy

비교

잡화점편의점온라인 잡화
# __init__.py from .foo import * from .bar import * from .baz import *# __init__.py
from .foo import foo_func
from .bar import bar_func
from .baz import baz_func
# __init__.py
import example_pkg.foo
import example_pkg.bar
import example_pkg.baz
import example_pkg example_pkg.foo_func() example_pkg.bar_func() example_pkg.baz_func()import example_pkg example_pkg.foo_func() example_pkg.bar_func() example_pkg.baz_func()import example_pkgexample_pkg.foo.foo_func()
example_pkg.bar.bar_func()
example_pkg.bar.baz_func()

or

from example_pkg import foo, bar, bazfoo.foo_func()
bar.bar_func()
baz.baz_func()

or

import example_pkg.foo as ex_foo
import example_pkg.bar as ex_bar
import example_pkg.baz as ex_bazex_foo.foo_func()
ex_bar.bar_func()
ex_baz.baz_func()

Leave a Reply

Your email address will not be published. Required fields are marked *