“import *”가 나쁜 이유는 무엇입니까?


153

import *파이썬 에서는 사용하지 않는 것이 좋습니다 .

누구든지 그 이유를 알려 주시면 다음에 그렇게하지 않도록 할 수 있습니까?



2
스크립트를 작성하거나 재사용해야하는 코드에 따라 다릅니다. 때로는 코드 표준을 무시하기 위해 비용을 지불합니다. "import *"는 이름 지정 규칙이 있으면 물건이 어디에서 왔는지 명확하게 할 수 있습니다. 예 : "Cats import *; TabbyCat; MaineCoonCat; CalicoCat;"
gatoatigrado

3
import *파이썬 2 나 3에서 처음에는 작동하지 않습니다.
joshreesjones

1
이것이 귀하의 질문에 대답합니까? "import *"는 정확히 무엇을 가져 옵니까?
AMC

답변:


223
  • 네임 스페이스에 많은 것들을 넣기 때문에 (이전 가져 오기에서 다른 객체를 음영 처리하고 알 수 없습니다).

  • 정확히 무엇을 가져올 지 모르고 어떤 모듈에서 어떤 모듈을 가져 왔는지 쉽게 찾을 수 없기 때문에 (가독성).

  • pyflakes코드에서 오류를 정적으로 감지하는 것과 같은 멋진 도구를 사용할 수 없기 때문 입니다.


2
그래, 나는 누군가가 수입을 사용할 때 정말로 내 일을 싫어한다. 왜냐하면 나는 pyflakes를 실행하고 행복 할 수는 없지만 수입품을 수리해야하기 때문이다. 그래도 그 pyflakes로 나를 도와줍니다 :-)
gruszczy

7
구체적인 예로서, NumPy의 많은 사용자들은 그들이 할 때 numpy.any그림자로 인해 물렸 거나 "유용한"도구가 그들을 위해 물었 습니다. anyfrom numpy import *
user2357112는 Monica

1
같은 이유로 IPython에 --pylab 스위치를 사용하지 않아야합니까?
timgeb

6
이 글을 읽기 전에 생각하지 못했던 위험을 강조하기 위해 ( "이전 임포트에서 다른 오브젝트를 쉐도우 할 수 있습니다") : 명령문 import *순서import중요하게합니다. 임포트 순서를 신경 쓰지 않는 표준 라이브러리 모듈에서도 . import수입 전쟁의 사상자가 사상자가 유일한 생존자가되었을 때, 당신의 진술 을 알파벳 순으로 무고한 것이 당신의 대본을 깨뜨릴 수 있습니다. (스크립트가 지금 작동하고 변경되지 않더라도 가져온 모듈에 의존했던 새 이름을 대체하는 새 이름이 도입되면 나중에 언젠가는 실패 할 수 있습니다.)
Kevin J. Chase

49

파이썬선에 따르면 :

암시적인 것보다 명시적인 것이 좋습니다.

... 논쟁 할 수 없어요?


29
사실, 당신 그것에 대해 논쟁 할 수 있습니다 . 파이썬에서 변수를 명시 적으로 선언하지 않으면 변수가 할당되면 존재하기 시작합니다.
Konrad Rudolph

7
@gruszczy : 변수 선언은 무엇에 중복 됩니까? 할당? 아니요, 그것은 두 개의 분리 된 개념이며 무언가를 선언하면 매우 독특하고 중요한 정보를 전달합니다. 어쨌든, 명시 성은 항상 중복성과 관련이 있으며, 같은 동전의 두면입니다.
Konrad Rudolph

3
@ kriss 맞습니다. 그러나 그것은 내 요점이 아닙니다. 내 요점은 변수를 명시 적으로 선언하지 않으면 오류가 발생한다는 것입니다. 당신은 "[선언]이없는 할당은 불가능하다"고 말합니다. 그러나 그것은 잘못입니다. 제 요점은 파이썬이 불행히도 정확히 가능하게한다는 것입니다.
Konrad Rudolph

3
@kriss 선언에 의해 컴파일러에 제공되는 또 다른 정보는 실제로 새 변수를 선언하려고한다는 사실입니다. 그것은 타입 시스템에 중요한 정보입니다. 당신은 현대 IDE가 잘못된 문제를 해결한다고 말하지만 그것은 잘못입니다. 사실 이것은 정적으로 컴파일되지 않은 언어에서 실질적인 문제이므로 Perl use strict(JavaScript var)이 추가되었습니다 . 물론 파이썬은 유형이 없습니다 (실제로 강력하게 유형이 지정됨). 어쨌든, 심지어 경우에 당신이 옳았이 여전히 파이썬의 선을 모순되는 것,이 답변에서 인용.
Konrad Rudolph

3
@kriss 잘못되었습니다 : 같은 변수 이름을 재사용해도 문제 가되지 않습니다 – 같은 변수를 재사용하면 (즉, 같은 범위의 같은 이름). 명시 적 선언은이 실수를 정확하게 막을 것입니다 (그리고 내가 말했듯이 간단한 엉킴에 기초한 다른 것들도 실제로는 매우 일반적이며 시간이 많이 걸리는 문제입니다. 언어). 그리고 필자가 주장하는 모순은 명시 적으로 요구하는 선의 요구 사항이며, 여기서는 실제로 창 밖으로 던져집니다.
Konrad Rudolph

40

**locals()기능에 전달 하지 않습니까?

파이썬은 "포함"문이 부족하기 때문에 그리고self 매개 변수를 명시 적이며, 그리고 다른 모듈을 읽지 않고 어떤 종류없이 - 범위 지정 규칙은 매우 간단합니다, 그 목적은 어디에서 오는 변수에 손가락을 가리키고에게 매우 쉽게 보통이다 IDE의 (어쨌든 언어가 매우 역동적이라는 사실에 의해 조사 방법으로 제한됨).

import *모든 것이 깨집니다.

또한 버그를 숨길 수도 있습니다.

import os, sys, foo, sqlalchemy, mystuff
from bar import *

이제 bar 모듈에 " os", " mystuff"등 ... 속성이 있으면 명시 적으로 가져온 속성을 무시하고 매우 다른 것을 가리킬 수 있습니다. 정의 __all__암시 적으로 가져옵니다 무엇이 상태 - - 바에서 현명한 종종 있지만 개체를 읽고 바 모듈을 분석하고 따르지 않고, 어디에서 온 여전히 그것을 추적하기 어렵다 자사의 수입. 네트워크 import *는 프로젝트 소유권을 가질 때 가장 먼저 수정하는 것입니다.

나를 오해하지 마십시오. 만약 import *빠진 것이 있으면 울고 싶습니다. 그러나 신중하게 사용해야합니다. 좋은 사용 사례는 다른 모듈 위에 파사드 인터페이스를 제공하는 것입니다. 마찬가지로, 조건부 가져 오기 문을 사용하거나 함수 / 클래스 네임 스페이스 내에서 가져 오기를 사용하려면 약간의 훈련이 필요합니다.

나는 중대형 프로젝트 또는 여러 기여자가있는 작은 프로젝트에서 최소한의 pyflakes를 실행하거나 올바르게 구성된 pylint를 실행하는 정적 분석 측면에서 최소한의 위생이 필요하다고 생각합니다. 그들은 일어난다.

물론 이것은 파이썬이기 때문에 규칙을 어 기고 탐구해야하지만 소스 코드가 규율이 없으면 열 배가 될 수있는 프로젝트에주의하십시오. 문제가 될 것입니다.


6
Python 2.x 에는 "include"문이 있습니다. 이라고 execfile()합니다. 운 좋게도 3.x에서는 거의 사용되지 않습니다.
Sven Marnach

방법에 대한 **vars()호출 된 함수가 다른 파일에있는 경우 전역을 포함하는? : P
Solomon Ucko

16

from ... import *대화식 세션에서 수행해도 됩니다.


doctest끈 안에서는 어떻습니까? 합니까 import *이 경우에는 "샌드 박스"내부 해석 GET을? 감사.
PatrickT

16

네임 스페이스를 오염시키기 때문입니다. 자신의 네임 스페이스에서 모든 함수와 클래스를 가져 오며, 정의한 함수와 충돌 할 수 있습니다.

또한 유지 관리 작업에는 정규화 된 이름을 사용하는 것이 더 명확하다고 생각합니다. 코드 라인 자체에서 함수의 출처를 알 수 있으므로 문서를 훨씬 쉽게 확인할 수 있습니다.

foo 모듈에서 :

def myFunc():
    print 1

귀하의 코드에서 :

from foo import *

def doThis():
    myFunc() # Which myFunc is called?

def myFunc():
    print 2


9

foo라는 모듈에 다음 코드가 있다고 가정 해보십시오.

import ElementTree as etree

그런 다음 자신의 모듈에 다음이 있습니다.

from lxml import etree
from foo import *

이제하는 어려운 디버그 모듈이 같은 모습 이 거기에 LXML의 etree을 가지고,하지만 정말 대신 ElementTree 있습니다.


7

이것들은 모두 좋은 대답입니다. 파이썬으로 새로운 사람들에게 코드를 작성하도록 가르 칠 때 다루는 import *것은 매우 어렵다고 덧붙입니다. 귀하 또는 그들이 코드를 작성하지 않았더라도 여전히 걸림돌입니다.

저는 어린이 (약 8 세)에게 Minecraft를 조작하기 위해 Python으로 프로그래밍하도록 가르치고 있습니다. 나는 그들에게 ( Atom Editor )와 함께 작업하고 REPL 주도 개발 ( bpython을 통해)을 가르치는 데 도움이되는 코딩 환경을 제공하고 싶습니다 . Atom에서 힌트 / 완료가 bpython만큼 효과적으로 작동한다는 것을 알았습니다. 운 좋게도 다른 통계 분석 도구와 달리 Atom은에 속지 않습니다 import *.

그러나,에 ... 예를 취할 수 있습니다 랩퍼이 그들이 from local_module import *포함 무리 모듈 블록의 목록을 . 네임 스페이스 충돌의 위험을 무시합시다. 이렇게하면 from mcpi.block import *모호한 유형의이 블록 전체 목록을 사용 가능하게 만들기 위해 살펴 봐야 할 것입니다. 대신을 사용한 경우 from mcpi import block입력 walls = block.하면 자동 완성 목록이 나타납니다. Atom.io 스크린 샷


6

사람들이 여기에 올린 유효한 포인트를 이해했습니다. 그러나 때로는 "스타 가져 오기"가 항상 나쁜 습관은 아니라는 주장이 있습니다.

  • 모든 상수가 다음과 같은 모듈로 이동하는 방식으로 코드를 구성하려는 경우 const.py:
    • 내가하면 import const모든 상수에 대해로 참조해야 const.SOMETHING합니다. 아마도 가장 편리한 방법은 아닙니다.
    • 내가 그렇게 from const import SOMETHING_A, SOMETHING_B ...하면 분명히 너무 장황하고 구조화의 목적을 무효화합니다.
    • 따라서이 경우에는 a를 수행하는 from const import *것이 더 나은 선택이라고 생각합니다.

4

다음 두 가지 이유로 매우 나쁜 습관입니다.

  1. 코드 가독성
  2. 변수 / 함수 등의 재정의 위험

들어 포인트 1 :하자이의 예를 참조하십시오

from module1 import *
from module2 import *
from module3 import *

a = b + c - d

여기에 코드를 보는에는 하나의 모듈에있는에 대한 아이디어를 얻을 것 b, c그리고 d실제로이 속한다.

다른 방법으로, 다음과 같이하면 :

#                   v  v  will know that these are from module1
from module1 import b, c   # way 1
import module2             # way 2

a = b + c - module2.d
#            ^ will know it is from module2

그것은 당신을 위해 훨씬 깨끗하고 팀에 합류하는 새로운 사람이 더 나은 아이디어를 가질 것입니다.

들어 포인트 2 :하자 모두 말 module1module2같은 변수가 b. 내가 할 때 :

from module1 import *
from module2 import *

print b  # will print the value from module2

여기에서 값 module1이 손실됩니다. b선언 된 경우에도 코드가 작동하지 않는 이유를 디버깅하기가 어려우며 module1코드 사용을 기대하는 코드를 작성했습니다.module1.b

다른 모듈에 동일한 변수가 있고 전체 모듈을 가져 오지 않으려면 다음을 수행하십시오.

from module1 import b as mod1b
from module2 import b as mod2b

2

테스트로서, 나는 "A 1"과 "B 1"을 각각 인쇄하는 2 개의 함수 A와 B를 가진 test.py 모듈을 만들었습니다. test.py를 다음과 같이 가져온 후 :

import test

. . . test.A () 및 test.B ()로 2 개의 함수를 실행할 수 있으며 "test"는 네임 스페이스에 모듈 로 표시 되므로 test.py를 편집하면 다음과 같이 다시로드 할 수 있습니다.

import importlib
importlib.reload(test)

그러나 내가 다음을 수행하면 :

from test import *

네임 스페이스에는 "test"에 대한 참조가 없으므로 대화식 세션에서 문제가되는 편집 후 (내가 알 수있는 한) 다시로드 할 방법이 없습니다. 다음 중 하나 :

import test
import test as tt

네임 스페이스에서 "test"또는 "tt"(각각)를 모듈 이름으로 추가하여 다시로드 할 수 있습니다.

만약 내가한다면:

from test import *

"A"와 "B"라는 이름은 네임 스페이스에 함수 로 표시됩니다 . test.py를 편집하고 위의 명령을 반복하면 수정 된 버전의 함수가 다시로드되지 않습니다.

그리고 다음 명령은 오류 메시지를 나타냅니다.

importlib.reload(test)    # Error - name 'test' is not defined

"from module import *"로로드 된 모듈을 다시로드하는 방법을 알고 있다면 게시하십시오. 그렇지 않으면 다음과 같은 형식을 피해야합니다.

from module import *

2

문서에서 제안한대로 import *프로덕션 코드 에서는 거의 사용하지 않아야 합니다.

가져 오는 동안 *A로부터 모듈 것은 나쁜, A로부터 *을 가져 패키지 것은 더 나쁜 것입니다. 기본적 으로 이전 명령문에 의해로드 된 패키지의 하위 모듈을 포함 from package import *하여 패키지에 의해 정의 된 모든 이름을 가져옵니다 .__init__.pyimport

그러나 패키지 __init__.py코드에서라는 이름의 목록을 정의하면 발견 __all__될 때 가져와야하는 하위 모듈 이름 목록으로 간주 from package import *됩니다.

이 예제를 고려하십시오 (에 __all__정의되어 있지 않다고 가정 sound/effects/__init__.py).

# anywhere in the code before import *
import sound.effects.echo
import sound.effects.surround

# in your module
from sound.effects import *

마지막 문은 문을 실행할 때 패키지에 정의되어 있기 때문에 echoand surround모듈을 현재 네임 스페이스로 가져옵니다 (이전 정의를 무시할 수 있음) .sound.effectsimport

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