import module
またはfrom module import
を使用するのが最善かどうかについて包括的なガイドを見つけようとしましたか? Pythonで始めたばかりで、ベストプラクティスを念頭に置いて始めようとしています。
基本的に、誰かが彼らの経験を共有できるか、他の開発者がどんな好みを持っているか、そして今後のgotchasを避けるための最良の方法は何かを望んでいたのですか?
import module
とfrom module import foo
の違いは主に主観的です。一番好きなものを選び、それを一貫して使用してください。ここに、決定に役立ついくつかのポイントがあります。
import module
import
ステートメントのメンテナンスの削減。モジュールの別のアイテムの使用を開始するために追加のインポートを追加する必要はありませんmodule.foo
を入力するのは面倒で冗長な場合があります(import module as mo
を使用してからmo.foo
と入力することで、tediumを最小限に抑えることができます)from module import foo
foo
を使用するための入力が少ないimport
ステートメントを更新する必要がありますfoo
に関するコンテキストが失われます。たとえば、ceil()
がmath.ceil()
に比べて何をするのかは明確ではありませんどちらの方法でもかまいませんが、do n't use from module import *
。
妥当な大規模なコードセットの場合、import *
を使用すると、モジュールにセメントで固定され、削除できなくなります。これは、コードで使用されているアイテムが「モジュール」からのものであるかどうかを判断するのが難しく、これ以上import
を使用しないと思うポイントに到達するのは簡単ですが、確認するのは非常に難しいからです。
ここには、モジュールへの書き込みに関連する、言及されていない別の詳細があります。確かにこれはあまり一般的ではないかもしれませんが、時々必要になりました。
Pythonでの参照と名前バインディングの動作方法により、モジュール内のシンボル(foo.barなど)をそのモジュールの外部から更新し、他のインポートコードにその変更を「参照」させる場合は、fooをインポートする必要があります特定の方法。例えば:
モジュール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の外側のコードはbarを「オレンジ」と見なしません。
import
対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
os
およびsys.modules
という名前の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'>
os
およびos.path
を使用して、globals()
およびlocals()
名前空間の辞書を確認します。
>>> 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
>>>
Locals()名前空間からos
を削除すると、sys.modulesに存在していても、os
およびos.path
にアクセスできなくなります。
>>> 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
os
およびsys.modules
で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()
名前空間の辞書でどのように見えるかを確認しましょう:
>>> 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'
>>>
os.path
ではなく、名前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
>>>
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
に傾いています。コードでオブジェクト/関数a lotを使用している場合は、from module import ...
を使用します。
私は個人的に常に使用しています
from package.subpackage.subsubpackage import module
そして、すべてにアクセスします
module.function
module.modulevar
理由は、同時に短い呼び出しがあり、各ルーチンのモジュール名前空間を明確に定義するためです。これは、ソースで特定のモジュールの使用を検索する必要がある場合に非常に便利です。
言うまでもなく、import *は使用しないでください。名前空間を汚染し、特定の関数がどこから来たか(どのモジュールから)を教えてくれないためです。
もちろん、次のように、2つの異なるパッケージの2つの異なるモジュールに同じモジュール名がある場合、トラブルで実行できます。
from package1.subpackage import module
from package2.subpackage import module
この場合、もちろんトラブルに直面しますが、パッケージレイアウトに欠陥があるという強力なヒントがあり、それを再考する必要があります。
import module
モジュールの多くの関数を使用する場合に最適です。
from module import function
function
のみが必要な場合に、モジュールのすべての関数と型でグローバル名前空間を汚染しないようにする場合に最適です。
言及されていない別の違いを次に示します。これは http://docs.python.org/2/tutorial/modules.html からそのままコピーされます
使用する場合は注意してください
from package import item
アイテムは、パッケージのサブモジュール(またはサブパッケージ)でも、関数、クラス、変数など、パッケージで定義された他の名前でもかまいません。 importステートメントは、最初にアイテムがパッケージで定義されているかどうかをテストします。そうでない場合、それはモジュールであると想定し、それをロードしようとします。見つからない場合、ImportError例外が発生します。
逆に、次のような構文を使用する場合
import item.subitem.subsubitem
最後のアイテムを除く各アイテムはパッケージでなければなりません。最後のアイテムはモジュールまたはパッケージにすることができますが、前のアイテムで定義されたクラス、関数、または変数にすることはできません。
これら2つの方法のもう1つの微妙な違いを発見しました。
モジュール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
を使用)。インポートが不要になって削除されたときに、問題のモジュールが壊れていました。
私も初心者なので、これを簡単な方法で説明しようとしています。Pythonには、次の3つのタイプのimport
ステートメントがあります。
1。一般的なインポート:
import math
このタイプのインポートは私の個人的なお気に入りですが、このインポート手法の唯一の欠点は、モジュールの機能を使用する必要がある場合、次の構文を使用する必要があることです:
math.sqrt(4)
もちろん、タイピングの労力が増えますが、初心者として、それに関連するモジュールと機能を追跡するのに役立ちます(優れたテキストエディターはタイピングの労力を大幅に削減し、推奨されます) 。
このimportステートメントを使用すると、入力の労力をさらに減らすことができます:
import math as m
今、math.sqrt()
を使用する代わりに、m.sqrt()
を使用できます。
2。関数のインポート:
from math import sqrt
このタイプのインポートは、コードがモジュールの単一または少数の関数にアクセスするだけの場合に最適ですが、モジュールの新しいアイテムを使用するにはimportステートメントを更新する必要があります。
3。ユニバーサルインポート:
from math import *
タイピングの労力を大幅に削減しますが、モジュールのさまざまな関数でコードを埋め、その名前がユーザー定義関数の名前と競合する可能性があるため、お勧めしません。example:
from x import *
について人々が言ったことに加えて、名前がどこから来たかを見分けるのをより難しくすることに加えて、これはPylintのようなコードチェッカーをスローします。これらの名前は未定義の変数として報告されます。
これに対する私自身の答えは、まず、使用するモジュールの数に依存します。 1つまたは2つだけを使用する場合、多くの場合、from
... import
を使用します。これにより、ファイルの残りの部分でのキーストロークが少なくなりますが、多くの異なるモジュールを使用する場合、import
を選択します。これは、各モジュール参照が自己文書化されることを意味するためです。探し回る必要なく、各シンボルの由来を確認できます。
通常、自己文書化スタイルのプレーンインポートを好み、インポートするモジュールが1つしかない場合でも、モジュール名を入力しなければならない回数が10から20を超えると、インポートのみに変更します。
驚くほど誰も話していないことがわかった重要な違いの1つは、プレーンimportを使用してprivate variable
とインポートされたモジュールからのprivate functions
は、from-importステートメントでは不可能です。
画像内のコード:
public_variable = 42
_private_variable = 141
def public_function():
print("I'm a public function! yay!")
def _private_function():
print("Ain't nobody accessing me from another module...usually")
import settings
print (settings._private_variable)
print (settings.public_variable)
settings.public_function()
settings._private_function()
# Prints:
# 141
# 42
# I'm a public function! yay!
# Ain't nobody accessing me from another module...usually
from settings import *
#print (_private_variable) #doesn't work
print (public_variable)
public_function()
#_private_function() #doesn't work
これに追加したいのですが、インポート呼び出し中に考慮すべきことがあります:
私は次の構造を持っています:
mod/
__init__.py
main.py
a.py
b.py
c.py
d.py
main.py:
import mod.a
import mod.b as b
from mod import c
import d
dis.disは違いを示します。
1 0 LOAD_CONST 0 (-1)
3 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (mod.a)
9 STORE_NAME 1 (mod)
2 12 LOAD_CONST 0 (-1)
15 LOAD_CONST 1 (None)
18 IMPORT_NAME 2 (b)
21 STORE_NAME 2 (b)
3 24 LOAD_CONST 0 (-1)
27 LOAD_CONST 2 (('c',))
30 IMPORT_NAME 1 (mod)
33 IMPORT_FROM 3 (c)
36 STORE_NAME 3 (c)
39 POP_TOP
4 40 LOAD_CONST 0 (-1)
43 LOAD_CONST 1 (None)
46 IMPORT_NAME 4 (mod.d)
49 LOAD_ATTR 5 (d)
52 STORE_NAME 5 (d)
55 LOAD_CONST 1 (None)
最終的には同じように見えます(各例でSTORE_NAMEが結果になります)が、次の4つの循環インポートを考慮する必要がある場合は注意が必要です。
foo/
__init__.py
a.py
b.py
a.py:
import foo.b
b.py:
import foo.a
>>> import foo.a
>>>
これは動作します
bar/
__init__.py
a.py
b.py
a.py:
import bar.b as b
b.py:
import bar.a as a
>>> import bar.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "bar\a.py", line 1, in <module>
import bar.b as b
File "bar\b.py", line 1, in <module>
import bar.a as a
AttributeError: 'module' object has no attribute 'a'
サイコロなし
baz/
__init__.py
a.py
b.py
a.py:
from baz import b
b.py:
from baz import a
>>> import baz.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "baz\a.py", line 1, in <module>
from baz import b
File "baz\b.py", line 1, in <module>
from baz import a
ImportError: cannot import name a
同様の問題...しかし、明らかにx import yはyとimport import x.yと同じではありません
qux/
__init__.py
a.py
b.py
a.py:
import b
b.py:
import a
>>> import qux.a
>>>
これも動作します
モジュールのインポート-モジュールから別のものを取得するための追加の作業は必要ありません。冗長な型付けなどの欠点があります
モジュールのインポート元-モジュールのどの項目にアクセスできるかをより少ない入力と詳細制御。モジュールから新しい項目を使用するには、インポート文を更新する必要があります。