180

import *Pythonでは使用しないことをお勧めします。

次回は避けられるように、その理由を教えてもらえますか?

4

12 に答える 12

250
  • 名前空間に多くのものを入れるためです(以前のインポートから他のオブジェクトをシャドウする可能性があり、それについてはわかりません)。

  • 何がインポートされているのか正確にはわからず、特定のものがどのモジュールからインポートされたのかを簡単に見つけることができないためです(読みやすさ)。

  • pyflakesコード内のエラーを静的に検出するようなクールなツールを使用できないためです。

于 2010-03-05T12:43:42.457 に答える
59

Pythonの禅によると:

明示的は暗黙的よりも優れています。

...確かに、それについて議論することはできませんか?

于 2010-03-05T13:17:04.870 に答える
42

関数に渡さ**locals()ないでしょ?

Pythonには「include」ステートメントがなくselfパラメーターは明示的であり、スコープ規則は非常に単純であるため、通常、変数に指を向けて、そのオブジェクトがどこから来たのかを判断するのは非常に簡単です。他のモジュールを読み取ったり、種類を指定したりする必要はありません。 IDEの(言語が非常に動的であるという事実により、とにかく内省の方法で制限されています)。

休憩はそれimport *をすべて壊します。

また、バグを隠す具体的な可能性もあります。

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

これで、barモジュールに " os"、 " mystuff"などの属性のいずれかがある場合、それらは明示的にインポートされた属性をオーバーライドし、場合によっては非常に異なるものを指します。バーで定義__all__するのは賢明なことがよくあります-これは暗黙的にインポートされるものを示します-それでも、バーモジュールを読み取って解析し、そのインポートを追跡しない限り、オブジェクトがどこから来たのかを追跡することは困難です。のネットワークはimport *、プロジェクトの所有権を取得するときに最初に修正するものです。

私を誤解しないでください:もしそれimport *が欠けていたら、私はそれを持っていると泣きます。ただし、慎重に使用する必要があります。良い使用例は、別のモジュール上にファサードインターフェイスを提供することです。同様に、条件付きインポートステートメントの使用、または関数/クラス名前空間内のインポートには、少しの規律が必要です。

中規模から大規模のプロジェクト、または複数の貢献者がいる小規模なプロジェクトでは、静的分析の観点から最小限の衛生状態が必要であると思います-少なくともパイフレークまたはさらに適切に構成されたピリントを実行して-以前にいくつかの種類のバグをキャッチしますそれらは起こります。

もちろん、これはpythonであるため、ルールを破って探索することもできますが、10倍に成長する可能性のあるプロジェクトには注意してください。ソースコードに規律がない場合は、問題になります。

于 2010-03-16T12:59:33.310 に答える
21

これは、名前空間を汚染しているためです。すべての関数とクラスを独自の名前空間にインポートします。これは、自分で定義した関数と衝突する可能性があります。

さらに、メンテナンスタスクでは、修飾名を使用する方が明確だと思います。関数の出所がコード行自体に表示されるので、ドキュメントをはるかに簡単にチェックできます。

モジュールfooの場合:

def myFunc():
    print 1

あなたのコードでは:

from foo import *

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

def myFunc():
    print 2
于 2010-03-05T12:45:55.563 に答える
19

from ... import *インタラクティブなセッションで行ってもかまいません。

于 2010-03-05T13:14:16.377 に答える
11

fooというモジュールに次のコードがあるとします。

import ElementTree as etree

そして、あなた自身のモジュールであなたは持っています:

from lxml import etree
from foo import *

これで、lxmlのetreeが含まれているように見えますが、実際には代わりにElementTreeが含まれているデバッグが難しいモジュールができました。

于 2010-03-05T13:18:20.343 に答える
11

人々がここに置いた有効なポイントを理解しました。ただし、「スターインポート」が必ずしも悪い習慣ではない場合があるという議論が1つあります。

  • すべての定数が次のモジュールに移動するようにコードを構造化する場合const.py
    • もしそうならimport const、すべての定数について、それをとして参照する必要がありますconst.SOMETHINGが、これはおそらく最も便利な方法ではありません。
    • 私がそうするならfrom const import SOMETHING_A, SOMETHING_B ...、明らかにそれはあまりにも冗長であり、構造化の目的を打ち負かします。
    • from const import *したがって、この場合、aを実行する方が良い選択かもしれないと感じています。
于 2016-12-26T08:57:57.493 に答える
10

http://docs.python.org/tutorial/modules.html

*一般に、モジュールまたはパッケージからインポートする方法は、コードの読み取りが困難になることが多いため、嫌われていることに注意してください。

于 2010-03-05T12:45:31.337 に答える
9

これらはすべて良い答えです。Pythonでコードを書くことを新しい人に教えるとき、対処するのimport *は非常に難しいことを付け加えておきます。あなたや彼らがコードを書かなかったとしても、それはまだつまずきです。

私は子供たち(約8歳)にMinecraftを操作するためにPythonでプログラムすることを教えています。私は彼らに(Atom Editor )で作業し、( bpythonを介して)REPL駆動開発を教えるのに役立つコーディング環境を提供したいと思います。Atomでは、ヒント/完了がbpythonと同じくらい効果的に機能することがわかりました。幸いなことに、他のいくつかの統計分析ツールとは異なり、Atomはにだまされませんimport *

ただし、この例を見てみましょう...このラッパーでは、このブロックのリストをfrom local_module import *含む多数のモジュールがあります。名前空間の衝突のリスクを無視しましょう。そうすることで、このあいまいなタイプのブロックのリスト全体を、何が利用できるかを知るために調べなければならないものにします。代わりにを使用していた場合は、入力するとオートコンプリートリストがポップアップ表示されます。 from mcpi.block import *from mcpi import blockwalls = block.Atom.ioスクリーンショット

于 2015-12-27T07:38:22.220 に答える
6

これは、次の2つの理由から非常に悪い習慣です。

  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の場合:両方module1を言い、module2変数を。として持ちます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
于 2016-11-09T23:05:58.297 に答える
2

テストとして、「A1」と「B1」をそれぞれ出力する2つの関数AとBを持つモジュールtest.pyを作成しました。test.pyをインポートした後:

import test

。。。2つの関数をtest.A()とtest.B()として実行でき、「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

「frommoduleimport*」でロードされたモジュールをリロードする方法を誰かが知っている場合は、投稿してください。そうでなければ、これはフォームを避ける別の理由になります:

from module import *
于 2017-05-03T01:41:34.520 に答える
2

ドキュメントで提案されているように、(ほとんど)import *本番コードでは使用しないでください。

モジュール*からのインポートは悪いですが、パッケージからの*のインポートはおそらくさらに悪いです。

デフォルトでは、前のステートメントによってロードされたパッケージのサブモジュールを含め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 *

最後のステートメントは、ステートメントの実行時にパッケージで定義されているため、モジュールを現在の名前空間にechoインポートします(以前の定義をオーバーライドする可能性があります) 。surroundsound.effectsimport

于 2019-01-25T16:16:01.710 に答える