[python] ‘모듈 가져 오기’또는 ‘모듈 가져 오기에서’를 사용 하시겠습니까?
사용하기에 가장 적합한 지 import module
또는 from module import
? 에 대한 포괄적 인 가이드를 찾으려고 노력했습니다 . 방금 Python으로 시작했으며 모범 사례를 염두에 두려고합니다.
기본적으로, 나는 누군가가 자신의 경험을 공유하고 다른 개발자가 선호하는 환경과 길을 잃지 않는 가장 좋은 방법은 무엇 입니까?
답변
import module
와 from 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 외부의 코드는 “오렌지”로 표시되지 않습니다.
답변
많은 사람들이 이미 import
vs import from
에 대해 설명했지만 , 후드에서 발생하는 일과 변경되는 모든 위치에 대해 조금 더 설명하려고합니다.
import foo
:
를 가져 와서 foo
현재 네임 스페이스에서 해당 모듈에 대한 참조를 만듭니다. 그런 다음 모듈 내부에서 특정 속성 또는 메소드에 액세스하려면 완료된 모듈 경로를 정의해야합니다.
예 foo.bar
아니지만bar
from foo import bar
:
을 가져 foo
오고 나열된 모든 멤버에 대한 참조를 만듭니다 ( bar
). 변수를 설정하지 않습니다 foo
.
예 : bar
하지만 baz
나foo.baz
from foo import *
:
를 가져 와서 foo
현재 네임 스페이스에서 해당 모듈에 의해 정의 된 모든 공용 객체에 대한 참조를 만듭니다 (있는 __all__
경우 나열된 __all__
모든 것, 그렇지 않으면로 시작하지 않는 모든 것 _
). 변수를 설정하지 않습니다 foo
.
예 bar
하고 baz
아니라 _qux
나 foo._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 os
및 os.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.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'>
우리 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
정의 된 것처럼 실수로 사용할 수 있습니다 .foo
itertools
import foo
foo.count()
foo
사용하는 경우 :
import itertools
실수는 여전히 가능하지만 그럴 가능성은 적습니다. bar
할 필요가있다:
import foo
foo.itertools.count()
이로 인해 몇 가지 문제가 발생했습니다. 실수로 모듈을 정의하지 않은 모듈에서 예외를 가져 왔으며 다른 모듈에서만 가져 왔습니다 (사용하여 from module import SomeException
). 가져 오기가 더 이상 필요하지 않고 제거되면 문제가되는 모듈이 손상되었습니다.