‘모듈 가져 오기’또는 ‘모듈 가져 오기에서’를 사용 하시겠습니까? 사용하기에 가장 적합한 지 import

사용하기에 가장 적합한 지 import module또는 from module import? 에 대한 포괄적 인 가이드를 찾으려고 노력했습니다 . 방금 Python으로 시작했으며 모범 사례를 염두에 두려고합니다.

기본적으로, 나는 누군가가 자신의 경험을 공유하고 다른 개발자가 선호하는 환경과 길을 잃지 않는 가장 좋은 방법은 무엇 입니까?



답변

import modulefrom module import foo주관적으로 차이가 있습니다. 가장 좋아하는 것을 골라 사용하십시오. 다음은 결정에 도움이되는 몇 가지 사항입니다.

import module

  • 장점 :
    • import진술의 유지 보수가 적습니다 . 모듈에서 다른 항목을 사용하기 위해 가져 오기를 추가 할 필요가 없습니다.
  • 단점 :
    • 입력하면 module.foo코드에서하는 것은 지루하고 중복 될 수 있습니다 (지루함을 사용하여 최소화 할 수 있습니다 import module as mo후 입력 mo.foo)

from module import foo

  • 장점 :
    • 사용하기에 적은 타이핑 foo
    • 액세스 할 수있는 모듈의 항목을보다 세밀하게 제어
  • 단점 :
    • 모듈에서 새 항목을 사용하려면 import명세서 를 업데이트해야 합니다
    • 에 대한 컨텍스트를 잃어 버립니다 foo. 예를 들어, 무엇에 ceil()비해 덜 명확 합니다math.ceil()

어느 방법이든 사용할 수 있지만를 사용 하지 마십시오 from module import *.

합리적인 대량의 코드 세트의 경우 import *모듈 에 코드를 시멘트로 만들면 제거 할 수 없습니다. 코드에서 사용되는 항목이 ‘모듈’에서 나오는 것을 결정하기가 어렵 기 때문에 import더 이상 사용하지 않는다고 생각하는 지점에 쉽게 도달 할 수는 있지만 확신하기가 매우 어렵습니다.


답변

모듈에 쓰는 것과 관련하여 언급되지 않은 또 다른 세부 사항이 있습니다. 이것이 일반적이지 않을 수도 있지만, 때때로 필요했습니다.

파이썬에서 참조 및 이름 바인딩이 작동하는 방식으로 인해 모듈 외부에서 foo.bar와 같은 모듈의 일부 기호를 업데이트하고 변경 사항을 “참조”하는 다른 가져 오기 코드가 있으면 foo a를 가져와야합니다. 특정 방식으로. 예를 들면 다음과 같습니다.

모듈 foo :

bar = "apples"

모듈 a :

import foo
foo.bar = "oranges"   # update bar inside foo module object

모듈 b :

import foo
print foo.bar        # if executed after a's "foo.bar" assignment, will print "oranges"

그러나 모듈 이름 대신 기호 이름을 가져 오면 작동하지 않습니다.

예를 들어, 모듈 a에서 이것을하면 :

from foo import bar
bar = "oranges"

bar 설정이 모듈 a 내부의 “bar”이름에만 영향을 미치기 때문에 foo 모듈 객체에 “도달”하고 “bar”를 업데이트하지 않기 때문에 a 외부의 코드는 “오렌지”로 표시되지 않습니다.


답변

많은 사람들이 이미 importvs import from에 대해 설명했지만 , 후드에서 발생하는 일과 변경되는 모든 위치에 대해 조금 더 설명하려고합니다.


import foo:

를 가져 와서 foo현재 네임 스페이스에서 해당 모듈에 대한 참조를 만듭니다. 그런 다음 모듈 내부에서 특정 속성 또는 메소드에 액세스하려면 완료된 모듈 경로를 정의해야합니다.

foo.bar아니지만bar

from foo import bar:

을 가져 foo오고 나열된 모든 멤버에 대한 참조를 만듭니다 ( bar). 변수를 설정하지 않습니다 foo.

예 : bar하지만 bazfoo.baz

from foo import *:

를 가져 와서 foo현재 네임 스페이스에서 해당 모듈에 의해 정의 된 모든 공용 객체에 대한 참조를 만듭니다 (있는 __all__경우 나열된 __all__모든 것, 그렇지 않으면로 시작하지 않는 모든 것 _). 변수를 설정하지 않습니다 foo.

bar하고 baz아니라 _quxfoo._qux.


이제 우리가 할 때 보자 import X.Y:

>>> import sys
>>> import os.path

sys.modules이름 os과 확인 os.path:

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

검사 globals()locals()와 네임 스페이스 dicts osos.path:

 >>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>

위의 예 os에서 로컬 및 글로벌 네임 스페이스 에만 삽입 된 것을 발견했습니다 . 따라서 다음을 사용할 수 있어야합니다.

 >>> os
 <module 'os' from
  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
 >>> os.path
 <module 'posixpath' from
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
 >>>

그러나 아닙니다 path.

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

당신이 삭제되면 os현지인 () 네임 스페이스를, 당신은에 액세스 할 수 없습니다 os아니라으로 os.path그들이 sys.modules에 존재하더라도 :

>>> del locals()['os']
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

이제 이야기 해 봅시다 import from:

from:

>>> import sys
>>> from os import path

확인 sys.modulesosos.path:

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

우리 sys.modules는 이전에 사용했던 것과 같은 것을 발견했습니다.import name

OK,하자 검사는이처럼 보이는 방법 locals()globals()dicts 네임 스페이스 :

>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>

다음이 path아닌 이름을 사용하여 액세스 할 수 있습니다 os.path.

>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

에서 ‘path’를 삭제합시다 locals():

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

별명을 사용하는 마지막 예 :

>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

경로가 정의되어 있지 않습니다.

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>

답변

두 가지 방법 모두 이유로 지원됩니다. 하나가 다른 것보다 더 적절한 경우가 있습니다.

  • import module: 모듈에서 많은 비트를 사용할 때 좋습니다. 단점은 각 참조를 모듈 이름으로 한정해야한다는 것입니다.

  • from module import ...: 가져온 항목은 모듈 이름 접두사없이 직접 사용할 수 있습니다. 단점은 사용하는 각 항목을 나열해야하며 코드의 출처가 명확하지 않다는 것입니다.

사용할 코드는 코드를 명확하고 읽기 쉽게 만드는 방법에 달려 있으며 개인 취향과 관련이 있습니다. import module코드에서 객체 또는 함수의 출처가 매우 명확하기 때문에 일반적으로 기울 입니다. 코드에서 from module import ...객체 / 함수를 많이 사용할 때 사용 합니다.


답변

나는 항상 개인적으로 사용합니다

from package.subpackage.subsubpackage import module

그런 다음 모든 것에 액세스하십시오.

module.function
module.modulevar

그 이유는 짧은 호출이있는 동시에 각 루틴의 모듈 네임 스페이스를 명확하게 정의하기 때문입니다. 소스에서 지정된 모듈의 사용법을 검색해야하는 경우 매우 유용합니다.

말할 필요도없이, import *를 사용하지 마십시오. 네임 네임 스페이스를 오염시키고 주어진 함수가 어디에서 왔는지 알려주지 않기 때문에 (어떤 모듈에서)

물론 두 개의 다른 패키지에서 두 개의 다른 모듈에 대해 동일한 모듈 이름을 사용하면 문제가 발생할 수 있습니다.

from package1.subpackage import module
from package2.subpackage import module

이 경우 당연히 문제가 발생하지만 패키지 레이아웃에 결함이 있음을 암시하고 다시 생각해야합니다.


답변

import module

모듈에서 많은 기능을 사용할 때 가장 좋습니다.

from module import function

필요할 때만 모듈에서 모든 함수와 유형으로 전역 네임 스페이스를 오염시키지 않으려는 경우에 가장 좋습니다 function.


답변

방금이 두 가지 방법 사이에 미묘한 차이가 있음을 발견했습니다.

모듈 foo이 다음 가져 오기를 사용하는 경우 :

from itertools import count

그러면 모듈 bar은 다음이 아닌에 count정의 된 것처럼 실수로 사용할 수 있습니다 .fooitertools

import foo
foo.count()

foo사용하는 경우 :

import itertools

실수는 여전히 가능하지만 그럴 가능성은 적습니다. bar할 필요가있다:

import foo
foo.itertools.count()

이로 인해 몇 가지 문제가 발생했습니다. 실수로 모듈을 정의하지 않은 모듈에서 예외를 가져 왔으며 다른 모듈에서만 가져 왔습니다 (사용하여 from module import SomeException). 가져 오기가 더 이상 필요하지 않고 제거되면 문제가되는 모듈이 손상되었습니다.