web-dev-qa-db-ja.com

Pythonの良いまたは悪い習慣:ファイルの途中でインポートする

比較的長いモジュールがあるが、外部モジュールまたはメソッドが1回だけ必要だとします。

モジュールの途中でそのメソッドまたはモジュールをインポートしても問題ありませんか?

または、importsはモジュールの最初の部分にのみ存在する必要があります。

例:

import string, pythis, pythat
...
...
...
...
def func():
     blah
     blah 
     blah
     from pysomething import foo
     foo()
     etc
     etc 
     etc
...
...
...

回答を正当化し、リンクを [〜#〜] pep [〜#〜] sまたは関連ソースに追加してください

55
flybywire

PEP 8 正式に述べる:

インポートは常にファイルの先頭、モジュールのコメントとドキュメント文字列の直後、モジュールのグローバルと定数の前に置かれます。

PEP 8は、すべての「社内」スタイルガイドの基礎となる必要があります。これは、コアPythonチームが全体として最も効果的なスタイルであることがわかったものをまとめたものです(もちろん、個々の意見には反対があります) 、他の言語と同様に、コンセンサスとBDFLはPEP 8)に同意します。

59
Alex Martelli

2001年にPythonメーリングリストでこのトピックの詳細な議論がありました:

https://mail.python.org/pipermail/python-list/2001-July/071567.html

17
ire_and_curses

他の誰もがすでにPEPについて言及していますが、重要なコードの途中にインポート文をnotにするように注意してください。少なくともPython 2.6の下では、関数にimportステートメントがある場合、さらにいくつかのバイトコード命令が必要です。

>>> def f():
    from time import time
    print time()

>>> dis.dis(f)
  2           0 LOAD_CONST               1 (-1)
              3 LOAD_CONST               2 (('time',))
              6 IMPORT_NAME              0 (time)
              9 IMPORT_FROM              0 (time)
             12 STORE_FAST               0 (time)
             15 POP_TOP             

  3          16 LOAD_FAST                0 (time)
             19 CALL_FUNCTION            0
             22 PRINT_ITEM          
             23 PRINT_NEWLINE       
             24 LOAD_CONST               0 (None)
             27 RETURN_VALUE

>>> def g():
    print time()

>>> dis.dis(g)
  2           0 LOAD_GLOBAL              0 (time)
              3 CALL_FUNCTION            0
              6 PRINT_ITEM          
              7 PRINT_NEWLINE       
              8 LOAD_CONST               0 (None)
             11 RETURN_VALUE  
16
Mark Rushakoff

インポートされたモジュールがあまり使用されず、インポートにコストがかかる場合、中間インポートは問題ありません。

それ以外の場合は、Alex Martelliの提案に従うのが賢明です。

11
Blauohr

これは一般に悪い習慣と考えられていますが、避けられない場合もあります(循環インポートを回避する必要がある場合など)。

必要なときの例:私は Waf を使用してすべてのコードをビルドします。システムはツールに分割され、各ツールは独自のモジュールに実装されています。各ツールモジュールは、前提条件が存在するかどうかを検出するdetect()メソッドを提供できます。これらの例の1つは、次のことを行います。

def detect(self):
    import foobar

これが正しく機能する場合、ツールは使用可能です。その後、同じモジュールでfoobarモジュールが必要になる可能性があるため、関数レベルのスコープで再度インポートする必要があります。明らかに、それがモジュールレベルでインポートされた場合、状況は完全に破壊されます。

8
jkp

ファイルの先頭ですべてのインポートをグループ化することは「適切な形式」と見なされます。

モジュールは他のモジュールをインポートできます。慣例ですが、すべてのインポートステートメントをモジュール(またはスクリプト)の先頭に配置する必要はありません。インポートされたモジュール名は、インポートモジュールのグローバルシンボルテーブルに配置されます。

ここから: http://docs.python.org/tutorial/modules.html

7
Frozenskys

95%の確率で、すべてのインポートをファイルの先頭に配置する必要があります。関数ローカルインポートを実行したい場合の1つは、循環インポートを回避するために実行する必要がある場合です。 foo.pyがbar.pyをインポートし、bar.pyの関数がfoo.pyから何かをインポートする必要があるとします。すべてのインポートを一番上に配置すると、まだコンパイルされていない情報に依存するファイルをインポートするときに予期しない問題が発生する可能性があります。この場合、関数をローカルインポートすると、コードが完全にコンパイルされ、関連する関数を呼び出すまで、コードが他のモジュールのインポートを保留できるようになります。

しかし、あなたのユースケースはfoo()がどこから来ているのかを明確にすることのほうが多いようです。この場合、私は次の2つのいずれかを優先します。

まず、というより

from prerequisite import foo

前提条件を直接インポートし、後でprerequisite.fooとして参照します。追加された冗長性は、コードの透過性を高めることで、スペードに戻ってきます。

または、(または上記と併せて)インポートとそれが使用されている場所との間の距離が本当に長い場合は、モジュールが大きすぎる可能性があります。他に何も使用しないインポートの必要性は、コードがより管理しやすいサイズのチャンクにリファクタリングされる可能性がある場所を示している可能性があります。

6
jcdyer

PEP8

インポートは常にファイルの先頭、モジュールのコメントとドキュメント文字列の直後、モジュールのグローバルと定数の前に置かれます。

インポートをスコープ指定することは悪い習慣ではありません。したがって、インポートはそれを使用した関数にのみ適用されます。

インポートがブロックの上部でグループ化されている場合や、ファイルの上部でグローバルに必要な場合は、コードが読みやすくなると思います。

2
Brian R. Bondy

まあ、私はファイルの先頭ですべてのインポートをグループ化することは良い習慣だと思う

2
jab