2

私はPythonを学んでいますが、今日はimportステートメントをどこに置くべきかを決定しようとしていたコードを書いています。

import ステートメントは、ほぼどこにでも配置できますが、その配置は、パフォーマンス、名前空間、およびまだわからないその他のことにどのように影響しますか?

4

5 に答える 5

4

公式の GoodPractice は、すべてのインポートをモジュールまたはスクリプトの先頭に配置することです。標準の lib モジュール / パッケージから始め、3 番目の部分、次にプロジェクト固有です。http: //www.python.org/dev/peps/pep を参照してください。 -0008/#インポート

実際には、循環依存関係のクイック&ダーティな回避策として、関数へのインポートを延期する必要がある場合があります(循環依存関係を解決する正しい方法は、別のモジュールで関連部分を抽出することですが、一部のフレームワークでは、Q&D を受け入れる必要がある場合があります回避策)。

「パフォーマンス」の理由で関数へのインポートを延期することは良い考えではありませんが、ルールを破る必要がある場合もあります。

モジュールのインポートとは、次のことを意味します。

search the module_or_package in `sys.modules`
if not found:
    search the module_or_package_source in `sys.path`
    if not found:
        raise an ImportError
    create a `module` instance from the module_or_package_source 
    # -> imply executing the top-level source code, which may raise anything
    store the `module` instance in `sys.modules`
bind the `module` name (or whatever name was imported from it) in the current namespace

wrt/ 「現在の名前空間」の意味は、実際には次のとおりです。ステートメントが実行される名前空間 (モジュールの「グローバル」、関数の「ローカル」、またはclassステートメントの本体) 。import3 つの例すべてを含む簡単なスクリプトを次に示します。

try:
    re
except NameError, e:
    print "name 're' is not yet defined in the module's namespace"
    print "module namespace : %s" % globals()

import re
print "name 're' is now defined in the module's namespace"
print "module namespace : %s" % globals()


def foo():
    try:
        os
    except NameError, e:
        print "name 'os' is not yet defined in the function's namespace"
        print "function namespace : %s" % locals()
        print "name 'os' is not defined in the module's namespace neither"
        print "module namespace : %s" % globals()

    import os
    print "name 'os' is now defined in the function's namespace"
    print "function namespace : %s" % locals()
    print "name 'os' is still not defined in the module's namespace"
    print "module namespace : %s" % globals()

foo()

print "After calling foo(), name 'os' is still not defined in the module's namespace"
print "module namespace : %s" % globals()

class Foo(object):
    try:
        os
    except NameError, e:
        print "name 'os' is not yet defined in the class namespace"
        print "but we cannot inspect this namespace now so you have to take me on words"
        print "but if you read the code you'll notice we can only get there if we have a NameError, so we have an indirect proof at least ;)"
        print "name 'os' is not defined in the module's namespace neither obvisouly"
        print "module namespace : %s" % globals()

    import os
    print "name 'os' is now defined in the class namespace"
    print "we still cannot inspect this namespace now but wait..."
    print "name 'os' is still not defined in the module's namespace neither"
    print "module namespace : %s" % globals()

print "class namespace is now accessible via Foo.__dict__"
print "Foo.__dict__ is %s" % (Foo.__dict__)
print "'os' is now an attribute of Foo - Foo.os = %s" % Foo.os
print "name 'os' is still not defined in the module's namespace"
print "module namespace : %s" % globals()
于 2013-10-10T10:32:48.373 に答える
0

使用する前に、ファイル内の任意の場所に配置できます。通常はループに入れるべき ではありませんが (期待どおりの結果が得られないため)、条件分岐に入れることはできます。インポートされたモジュールの初期化コードが実行されるため、それが必要になることがわかっている場合にのみロードすることで、少し時間を節約できます。

関数内に配置できます、関数内にある場合は、その関数内でのみスコープ内になります。例えば

>>> def f1():
...    import sys
...    print sys.version
...
>>> def f2():
...    print sys.version
...
>>> f2()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f2
NameError: global name 'sys' is not defined
>>> f1()
2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)]
>>> f2()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f2
NameError: global name 'sys' is not defined
>>>

従うべき良い規則は、ファイルの先頭に配置して、常に利用可能で見つけやすいようにすることです。

また、特にパッケージ コンポーネントをテストする場合、いくつかのインポートの前に sys.path を変更する必要がある場合があるため、早期にインポートする必要があります。

私が個人的に便利だと思う規則は、すべてのシステム インポートを最初に行い、次にプロジェクト パッケージのインポート、次にローカル インポートを間に適切なコメントを付けて行うことです。

import modulenamefrom モジュール import サブモジュール、またはimport モジュール as エイリアスの場合、インポート順序に大きな違いはありませんが、from モジュール の場合、さまざまなモジュールが同じ名前を定義でき、最後が取得されるため、すべての賭けはオフになります-これは理由の 1 つにすぎimport *ませ それが落胆していること。

于 2013-10-10T09:59:00.590 に答える
0

モジュールが最初にインポートされると、Python はモジュールを検索し、見つかった場合はモジュール オブジェクトを作成します。

モジュールのサイズとコード内での使用頻度に応じて、ファイルの先頭に一度だけインポートしたり、特定の条件が満たされたときにインポートしたりすることができます。 .

システム メモリは常に制約されています - モジュールの前述の条件が非常に少数のケースで満たされる可能性が高い場合は、条件チェックに基づいてインポートするのが理にかなっています。

これは、それぞれが多くのメモリを消費する複数の重いモジュールをコードにインポートする必要がある場合に特に役立ちますが、それらはさまざまな場所で必要になります。だから、そのようにするのではなく

import module1 
import module2

def foo1()
    module1.function()
def foo2()
    module2.function()
foo1()
foo2()

次のようなものを試してください

def foo1()
    import module1 
    module1.function()
def foo2()
    import module2
    module2.function()
foo1()
foo2()

Python モジュールが十分に単純な場合は、それらをファイルの先頭に含めるのが理にかなっています。そうすれば、コードを読んでいる他の人も、現在のコードがどのモジュールを使用しているかを事前に理解できます。

于 2013-10-10T09:56:12.700 に答える