'가져 오기 모듈'대 '모듈 가져 오기 기능에서'


143

나는 항상이 방법을 사용하고있다 :

from sys import argv

argvargv 만 사용하십시오 . 그러나 이것을 사용하는 규칙이 있습니다.

import sys

에 의해 argv를 사용하여 sys.argv

두 번째 방법은 코드를 자체 문서화하고 나는 (실제로) 준수합니다. 그러나 첫 번째 방법을 선호하는 이유는 전체 모듈을 가져 오는 대신 필요한 함수 만 가져 오기 때문에 빠릅니다 (파이썬은 가져 오는 데 시간이 낭비되는 쓸모없는 함수가 포함되어 있음). argv가 필요하며 sys의 다른 모든 기능은 나에게 쓸모가 없습니다.

내 질문은 첫 번째 방법은 실제로 스크립트를 빠르게 만드는가? 어떤 방법이 가장 선호됩니까? 왜?



답변:


175

모듈을 가져 오는 것은 아무 것도 낭비하지 않습니다 . 모듈은 항상 ( 매핑으로) 완전히 가져 sys.modules오기 때문에 사용 import sys하거나 from sys import argv승산하지 않습니다.

두 문장의 유일한 차이점은 이름이 바인드 된 것입니다. import sys이름 결합 sys모듈로 (그래서 sys-> sys.modules['sys'])가 동시에 from sys import argv서로 다른 이름을 바인딩 argv모듈의 내부에 포함되는 속성에 셔널 (그래서 argv-> sys.modules['sys'].argv). sys모듈의 다른 것을 사용하든 아니든, 나머지 모듈은 여전히 ​​존재합니다.

또한 두 접근 방식간에 성능 차이는 없습니다. 예, sys.argv두 가지를 찾아야합니다. sys전역 네임 스페이스에서 찾아보고 (모듈을 찾음) 속성을 찾아야합니다 argv. 그리고 예, from sys import argv이미 속성에 대한 직접적인 참조가 있으므로 속성 검색을 건너 뛸 수 있습니다. 그러나 import진술은 여전히 ​​그 일을해야하며 가져 오기 할 때 동일한 속성을 찾고 argv 한 번만 사용해야 합니다 . argv루프에서 수천 번 사용해야한다면 아마도 차이가 생길 수 있지만이 경우에는 실제로 그렇지 않습니다.

그러면 둘 중 하나를 선택하는 것이 코딩 스타일을 기반으로해야합니다 .

A의 대형 모듈, 나는 확실히 사용하십시오 import sys; 코드 문서가 중요 sys.argv하고 큰 모듈에서 어딘가에 사용 하면 이전보다 훨씬 명확하게 참조 할 argv수 있습니다.

당신이 사용하는 유일한 장소 가 함수 를 호출하기 argv위해 '__main__'블록 안에 있다면, 그것에 대해 더 행복하다고 느끼면 반드시 main()사용 from sys import argv하십시오 :

if __name__ == '__main__':
    from sys import argv
    main(argv)

나는 여전히 import sys저 자신을 사용 합니다. 모든 것이 평등하고 (그리고 정확하게 쓰는 데 사용되는 문자 수 성능면에서 ), 그것은 나에게 더 쉽습니다.

다른 것을 모두 가져 오는 경우 성능이 향상 될 수 있습니다. 그러나 예를 들어 중요한 루프 와 같이 모듈에서 특정 이름을 여러 번 사용하는 경우에만 가능합니다 . 그러나 함수 내에서 로컬 이름을 만드는 것이 여전히 더 빠릅니다.

 import somemodule

 def somefunction():
      localname = somemodule.somefunctionorother
      while test:
          # huge, critical loop
          foo = localname(bar)

1
최상위 패키지에 하위 패키지 / 모듈 중 하나의 속성을 표시하는 하위 패키지 또는 모듈이 포함 된 패키지가있는 경우도 있습니다. 사용 from...import당신이 할 수 있습니다 package.attribute보다는 package.subpackage_or_module.attribute패키지 내에서 논리적 또는 개념 그룹을 가지고 있지만 패키지의 사용자를위한 일을 좀 더 편리하게하려는 경우 유용 할 수있다. ( numpy이것이 믿습니다.)
JAB

장고 from django.core.management.base import BaseCommand에는 더 나은 곳이 많고 다른 곳 (특히 import django)으로 읽을 수없는 코드가 생길 수있는 많은 곳이 있습니다. 따라서이 답변을 좋아하지만 컨벤션이 베어 임포트를 위반하는 라이브러리 (특히 일부 프레임 워크)가 있다고 생각합니다. 항상 그렇듯이 주어진 상황에서 가장 좋은 것에 대한 판단을 사용하십시오. 그러나 명시 적 측면에서 실수하십시오 (즉, 대부분 동의합니다).
neuronet

1
@JAB : 여전히 import ... as다른 이름으로 패키지를 찾는 데 사용할 수 있습니다 : import package.subpackage_or_module as shortname. from parent import sub본질적으로 같은 일을합니다.
Martijn Pieters

43

을 사용 import module하는 대신에 두 가지 이유 가 from module import function있습니다.

첫 번째는 네임 스페이스입니다. 전역 네임 스페이스로 함수를 가져 오면 이름 충돌이 발생할 수 있습니다.

두 번째는 표준 모듈과 관련이 없지만, 특히 개발 중에는 모듈을 소유하는 경우 중요합니다. reload()모듈에 대한 옵션 입니다. 이걸 고려하세요:

from module import func
...
reload(module)
# func still points to the old code

반면에

import module
...
reload(module)
# module.func points to the new code

속도는 ...

우리는 전체 모듈을 가져 오는 대신 필요한 함수 만 가져옵니다 (파이썬은 가져 오는 데 시간이 낭비되는 쓸모없는 함수가 포함되어 있습니다)

모듈을 가져 오든 모듈에서 함수를 가져 오든 관계없이 Python은 전체 모듈을 구문 분석합니다. 모듈을 가져 오는 방법 중 하나입니다. "함수 가져 오기"는 함수를 이름에 바인딩하는 것 이상입니다. 사실 import module통역사보다 일이 적습니다 from module import func.


6
reload ()는 Python 2에서 기본 제공되었습니다. 그것은 더 이상 파이썬 3의 경우가 아닙니다.
André

순환 수입 의존성과 관련이 있다고 생각 했습니까?
ADP

18

from import가독성을 향상시킬 때마다 s를 사용 합니다. 예를 들어, 나는 선호합니다 (세미콜론은 여기 공간을 절약하기위한 것입니다).

from collections import defaultdict
from foomodule import FooBar, FooBaz
from twisted.internet.protocol import Factory
defaultdict(); FooBar(); FooBaz(); Factory()

대신에:

import collections
import foomodule
import twisted.internet.protocol
collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz()
twisted.internet.protocol.Factory()

후자는 너무 많은 중복 정보가 포함되어 있기 때문에 읽기 및 쓰기가 더 어렵습니다. 또한 내가 사용하는 모듈의 부분을 미리 아는 것이 유용합니다.

import모듈에서 짧은 이름을 많이 사용하는 경우 일반을 선호 합니다.

import sys
sys.argv; sys.stderr; sys.exit()

또는 이름이 너무 일반적인 경우 네임 스페이스 외부에서는 의미가 없습니다.

import json
json.loads(foo)

from json import loads
loads(foo)  # potentially confusing

이것은 내가 가장 좋아하는 답변입니다. '명시 성이 암시 적보다 낫다'는 가독성, 단순성 및 DRY와 충돌하는 경우가 있습니다. 특히 장고와 같은 프레임 워크를 사용할 때.
neuronet

18

내 생각에 정기적으로 사용 import하면 가독성이 향상됩니다. 파이썬 코드를 검토 할 때 주어진 함수 또는 클래스가 사용되는 곳에서 오는 것을 보는 것이 좋습니다. 그것은 정보를 얻기 위해 모듈 상단으로 스크롤하는 것을 막아줍니다.

긴 모듈 이름에 대해서는 as키워드를 사용하고 짧은 별칭을 지정하십시오.

import collections as col
import foomodule as foo
import twisted.internet.protocol as twip

my_dict = col.defaultdict()
foo.FooBar()
twip_fac = twip.Factory()

예외적으로 나는 모듈을 from module import something다룰 때 항상 표기법을 사용합니다 __future__. 파이썬 2에서 기본적으로 모든 문자열을 유니 코드로 만들려면 다른 방법으로 할 수 없습니다.

from __future__ import unicode_literals
from __future__ import print_function

아멘! "가져 오기"는 우승 조합입니다 :-)
paj28

4

하지만 import sys하고 from sys import agrv모두 전체 수입 sys모듈을, 후자의 용도는 그래서에만 바인딩의 이름을 argv모듈하는 코드의 나머지 부분에 액세스 할 수 있습니다.

일부 사람들에게는 명시 적으로 언급 한 기능에만 액세스 할 수 있기 때문에 이것이 선호되는 스타일입니다.

그러나 이름 충돌 가능성이 있습니다. 다른 모듈이 있다면 argv어떨까요? 명시 적으로 가져 오기 from sys import argv as sys_argv를 충족하고 네임 스페이스 충돌이 발생할 가능성이 적은 규칙을 사용하여 함수를 명시 적으로 가져 와서 이름을 바꿀 수도 있습니다 .


2
그렇다면 어떻게 if sys_argv:if sys.argv:습니까? 나는 두 번째 진술이 무엇을 의미하는지 알고, 기괴한 수입으로 역 추적하지 않고 첫 번째 양식이 무엇을 의미하는지 전혀 모른다.
msw

1

나는 최근에이 질문을 스스로에게 물었다. 다른 방법을 사용했습니다.

요청 라이브러리

def r():
    import requests
    return 'hello'
timeit r() # output: 1000000 loops, best of 3: 1.55 µs per loop

def rg():
    from requests import get
    return 'hello'
timeit rg() # output: 100000 loops, best of 3: 2.53 µs per loop

beautifulsoup 라이브러리

def bs():
    import bs4
    return 'hello' 
timeit bs() # output: 1000000 loops, best of 3: 1.53 µs per loop

def be():
    from bs4 import BeautifulSoup
    return 'hello'
timeit be() # output: 100000 loops, best of 3: 2.59 µs per loop

JSON 라이브러리

def js():
    import json
    return 'hello'
timeit js() # output: 1000000 loops, best of 3: 1.53 µs per loop

def jl():
    from json import loads
    return 'hello'
timeit jl() # output: 100000 loops, best of 3: 2.56 µs per loop

sys 라이브러리

def s():
    import sys
    return 'hello'
timeit s() # output: 1000000 loops, best of 3: 1.55 µs per loop

def ar():
    from sys import argv
    return 'hello'
timeit ar() # output: 100000 loops, best of 3: 2.87 µs per loop

성능에 약간의 차이 있는 것 같습니다 .


속성 조회를 추가하고 있습니다. 비교하기 import modulefrom module import name올바르게 추가 받는 그 이름 조회를 import module하는 경우. 예 sys.argv를 들어 ar테스트에 행 을 추가하십시오 . 다른 바이트 코드가 생성되고 다른 코드 경로가 실행되므로 수행되는 작업이 약간 다르기 때문에 여전히 차이가 있습니다 .
Martijn Pieters

2
나는 그 대답의 차이를 직접적으로 언급한다. 사용의 차이가있을 것입니다 import sys후 사용 sys.argv루프에서 시간의 수천 대 from sys import argv그럼 그냥 사용 argv. 그러나 당신은하지 않습니다. 모듈의 전역 수준에서 한 번만 수행하는 작업의 경우 미세한 타이밍 차이가 아니라 가독성을 최적화해야합니다.
Martijn Pieters

1
아아! 그리고 나는 내가 무언가에 있다고 생각했습니다! :) 나는 단지 당신의 대답을 훑어 보았습니다. 내가 그 총에 뛰어 들었던 것 같습니다. 겸손 해지는 것이 좋습니다.
tmthyjames

-1

게시 된 코드 조각을보고 전체 모듈을 가져오고 참조하는 module.function것은 최소한 표준 모듈의 경우 거의 표준입니다. 한 가지 예외는datetime

from datetime import datetime, timedelta

datetime.now()보다 말할 수 있습니다 datetime.datetime.now().

성능이 염려된다면 언제든지 (예를 들어) 말할 수 있습니다.

argv = sys.argv

그런 다음 모듈 조회가 이미 완료되었으므로 성능에 중요한 코드를 수행하십시오. 그러나 이것이 함수 / 메소드와 함께 작동하지만 대부분의 IDE는 혼동되어 함수에 변수에 할당 될 때 함수에 대한 소스 링크 / 서명을 표시하지 않습니다.


-2

나는 당신이 같은 것을하면 그것을 추가하고 싶습니다.

from math import sin

(또는 다른 내장 된 라이브러리와 같은 sys이상이 posix) 다음, sin당신이 즉, 모듈 (대한 문서에 포함됩니다 >>> help(mymodule)또는 $ pydoc3 mymodule이를 방지하기 위해 수입 사용. :

import math
from math import sin as _sin

추신 : 내장 라이브러리는 C 코드에서 컴파일되고 Python에 포함 된 라이브러리입니다. argparse, osio내장되지 않은 패키지

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.