Pythonでモジュールをインポートできる多数の方法に少し混乱しています。
import X
import X as Y
from A import B
私はスコーピングと名前空間について読んでいますが、どのような状況と理由で最良の戦略が何であるかについて、実用的なアドバイスが欲しいです。インポートはモジュールレベルまたはメソッド/関数レベルで行う必要がありますか?の中に __init__.py
またはモジュールコード自体に?
私の質問は、「 Pythonパッケージ-ファイルではなくクラスによるインポート 」では実際には答えられませんが、明らかに関連しています。
当社の製品コードでは、次のルールに従うようにしています。
ファイルの先頭、メインファイルのdocstringの直後にインポートを配置します。例:
"""
Registry related functionality.
"""
import wx
# ...
インポートされたモジュールの数少ないクラスの1つをインポートする場合、名前を直接インポートするため、コードでは最後の部分のみを使用する必要があります(例:
from RegistryController import RegistryController
from ui.windows.lists import ListCtrl, DynamicListCtrl
ただし、多数のクラスを含むモジュールがあります。考えられるすべての例外のリスト。次に、モジュール自体をインポートし、コードでそれを参照します。
from main.core import Exceptions
# ...
raise Exceptions.FileNotFound()
特定のモジュールまたはクラスの使用を検索することが困難になるため、import X as Y
を使用することはほとんどありません。ただし、同じ名前であるが異なるモジュールに存在する2つのクラスをインポートする場合は、使用する必要がある場合があります。例:
from Queue import Queue
from main.core.MessageQueue import Queue as MessageQueue
一般的なルールとして、メソッド内部でのインポートは行いません。単にコードを遅くして読みにくくします。これは、周期的なインポートの問題を簡単に解決するための良い方法であると感じるかもしれませんが、より良い解決策はコードの再編成です。
Guido van Rossumが始めたDjango-devメーリングリストに会話の一部を貼り付けてみましょう。
[...]たとえば、Google Pythonスタイルガイド[1]の一部であり、すべてのインポートは、そのモジュールのクラスまたは関数ではなく、モジュールをインポートする必要があります。モジュールよりも機能があるため、モジュール名の接頭辞を付けると、特定のものがどこから来たのかを思い出すのがはるかに簡単になります。多くの場合、複数のモジュールが同じ名前の物を定義するため、コードの読者はファイルの先頭に戻って、指定された名前がインポートされているモジュールを確認します。
出典:http://groups.google.com/group/Django-developers/browse_thread/thread/78975372cdfb7d1a
1: http://code.google.com/p/soc/wiki/PythonStyleGuide#Module_and_package_imports
通常、モジュールレベルでimport X
を使用します。モジュールの単一オブジェクトのみが必要な場合は、from X import Y
を使用します。
名前の衝突に直面した場合にのみ、import X as Y
を使用してください。
モジュールをメインモジュールとして使用するときに必要なものをインポートするには、関数レベルでインポートのみを使用します。
def main():
import sys
if len(sys.argv) > 1:
pass
HTH
上記の誰かが言った
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
に等しい
import X
import X
はA-Pを直接変更できますが、from X import ...
はA-Pのコピーを作成します。にとって from X import A..P
変数が変更された場合、変数は更新されません。それらを変更する場合、コピーのみを変更しますが、Xは変更を認識します。
A-Pが関数の場合、違いはわかりません。
他の人がここで大部分をカバーしましたが、クラスまたはモジュールの新しいバージョンを試すときに、import X as Y
(一時的に)を使用する1つのケースを追加したかっただけです。
したがって、モジュールの新しい実装に移行するが、コードベースを一度にすべてカットしたくない場合は、xyz_new
モジュールを記述し、移行したソースファイルでこれを行うことができます。 :
import xyz_new as xyz
次に、コードベース全体をカットしたら、xyz
モジュールをxyz_new
に置き換え、すべてのインポートを
import xyz
これをしないでください:
from X import *
そのモジュール内のすべてのものを使用することを絶対に確信していない限り。その場合でも、おそらく別のアプローチを使用することを再検討する必要があります。
それ以外は、スタイルの問題です。
from X import Y
良いし、多くの入力を節約できます。私はかなり頻繁に何かを使用しているときにそれを使用する傾向がありますが、そのモジュールから多くをインポートしている場合、次のようなインポートステートメントになる可能性があります:
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
あなたはアイデアを得る。それはインポートのようなときです
import X
有用になります。それか、私が実際にXで頻繁に何かを使用していない場合。
私は通常、モジュール名が長いか頻繁に使用されない限り、通常の_import modulename
_を使用しようとします。
たとえば、私は….
_from BeautifulSoup import BeautifulStoneSoup as BSS
_
..so soup = BSS(html)
の代わりにBeautifulSoup.BeautifulStoneSoup(html)
を実行できます
または..
_from xmpp import XmppClientBase
_
..XmppClientBaseのみを使用する場合、xmpp全体をインポートする代わりに
_import x as y
_を使用すると、非常に長いメソッド名をインポートしたり、既存のimport/variable/class/methodを上書きしたくない場合に便利です(完全に回避しようとするべきですが、常に可能であるとは限りません)
別のスクリプトからmain()関数を実行したいが、すでにmain()関数があるとします。
_from my_other_module import main as other_module_main
_
..私のmain
関数をmy_other_moduleのmain
に置き換えません
ああ、一つのこと-_from x import *
_をしないでください-メソッドがどこから来たのかを簡単に見ることができないため、コードを理解するのが非常に難しくなります(from x import *; from y import *; my_func()
-my_funcはどこで定義されていますか?)
すべての場合において、couldだけ_import modulename
_を実行し、その後modulename.subthing1.subthing2.method("test")
...を実行します.
_from x import y as z
_のものは純粋に便宜上のものです-コードの読み取りまたは書き込みが容易になる場合はいつでも使用してください!
よく書かれたライブラリがある場合(Pythonの場合もあります)、それをインポートしてそのまま使用する必要があります。よく書かれたライブラリは、それ自体が命と言語を必要とする傾向があり、読みやすいコードになりますが、ライブラリを参照することはほとんどありません。ライブラリが適切に作成されている場合は、名前の変更などを頻繁に行う必要はありません。
import gat
node = gat.Node()
child = node.children()
このように書くことができない場合や、インポートしたライブラリから物事を削除したい場合があります。
from gat import Node, SubNode
node = Node()
child = SubNode(node)
インポート文字列が80列をオーバーフローする場合、多くのことに対してこれを行うことがあります。これを行うことをお勧めします。
from gat import (
Node, SubNode, TopNode, SuperNode, CoolNode,
PowerNode, UpNode
)
最善の戦略は、これらのインポートをすべてファイルの先頭に保持することです。アルファベット順が望ましい。最初に-statementsをインポートし、次にimport -statementsからインポートします。
さて、なぜこれが最高のコンベンションなのかをお話しします。
Pythonは、自動インポートを完全に行うことができました。これは、グローバルネームスペースから値が見つからない場合、メインインポートから値を探します。しかし、これは良い考えではありません。理由を簡単に説明します。単純なインポートよりも実装が複雑なことを除けば、プログラマーは依存関係についてあまり考えず、インポートを調べる以外の方法でインポートする場所を見つける必要はありません。
依存関係を見つける必要があることが、人々が「from ... import *」を嫌う理由の1つです。ただし、opengl -wrappingsなど、これを行う必要がある悪い例がいくつかあります。
したがって、インポート定義は、プログラムの依存関係を定義するのに実際に役立ちます。それはあなたがそれらを活用する方法です。それらから、奇妙な関数のインポート元を簡単に確認できます。
私は使用していないという事実でジェイソンと一緒です
from X import *
しかし、私の場合(私は熟練したプログラマーではないので、私のコードはコーディングスタイルにあまり適合していません)、私は通常、プログラムバージョン、作成者、エラーメッセージなどのすべての定数を含むファイルをプログラムで実行します。ファイルは単なる定義なので、インポートを行います
from const import *
それは私に多くの時間を節約します。しかし、それはそのインポートを持つ唯一のファイルであり、そのファイル内のすべてが単なる変数宣言であるためです。
クラスと定義を含むファイルでこの種のインポートを行うと便利な場合がありますが、そのコードを読み取る必要がある場合は、関数とクラスの検索に多くの時間を費やします。
import X as Y
は、同じモジュール/クラスの異なる実装がある場合に役立ちます。
ネストされたtry..import..except ImportError..import
sコードから実装を隠すことができます。 lxml etreeインポートの例 を参照してください:
try:
from lxml import etree
print("running with lxml.etree")
except ImportError:
try:
# Python 2.5
import xml.etree.cElementTree as etree
print("running with cElementTree on Python 2.5+")
except ImportError:
try:
# Python 2.5
import xml.etree.ElementTree as etree
print("running with ElementTree on Python 2.5+")
except ImportError:
try:
# normal cElementTree install
import cElementTree as etree
print("running with cElementTree")
except ImportError:
try:
# normal ElementTree install
import elementtree.ElementTree as etree
print("running with ElementTree")
except ImportError:
print("Failed to import ElementTree from any known place")