74

Pythonでモジュールをインポートする方法がたくさんあることに少し混乱しています。

import X
import X as Y
from A import B

私はスコーピングと名前空間について読んでいますが、どのような状況で、なぜ最良の戦略が何であるかについて、いくつかの実用的なアドバイスが欲しいです。インポートはモジュールレベルまたはメソッド/関数レベルで行う必要がありますか?__init__.pyまたはモジュールコード自体に?

私の質問は、明らかに関連していますが、「 Pythonパッケージ-ファイルではなくクラスでインポートする」では実際には答えられません。

4

10 に答える 10

68

当社の本番コードでは、以下のルールを守っています。

インポートは、ファイルの先頭、メインファイルの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

原則として、メソッド内でのインポートは行いません。メソッドを使用すると、コードが遅くなり、読みにくくなります。これは循環インポートの問題を簡単に解決するための良い方法だと思う人もいるかもしれませんが、より良い解決策はコードの再編成です。

于 2008-10-11T10:15:40.457 に答える
39

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

于 2008-10-11T18:34:42.087 に答える
12

私は通常import X、モジュールレベルで使用します。モジュールからのオブジェクトが1つだけ必要な場合は、を使用しますfrom X import Y

import X as Y名前の衝突に直面した場合にのみ使用してください。

次のように、モジュールがメインモジュールとして使用されるときに必要なものをインポートするために、関数レベルでのインポートのみを使用します。

def main():
  import sys
  if len(sys.argv) > 1:
     pass

HTH

于 2008-10-11T10:10:13.417 に答える
5

import X as Y他の人がここで大部分をカバーしていますが、新しいバージョンのクラスまたはモジュールを試すときに (一時的に)使用するケースを 1 つ追加したかっただけです。

したがって、モジュールの新しい実装に移行するが、一度にコード ベース全体を切り詰めたくない場合は、xyz_newモジュールを作成し、移行したソース ファイルでこれを行うことができます。

import xyz_new as xyz

次に、コード ベース全体を切り取ったら、xyzモジュールを置き換えて、xyz_newすべてのインポートを元に戻します。

import xyz
于 2008-10-11T13:49:34.970 に答える
3

これをしないでください:

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で何も頻繁に使用していない場合。

于 2008-10-11T14:00:13.000 に答える
2

import modulenameモジュール名が長い場合や頻繁に使用する場合を除いて、私は通常、通常のを使用しようとします..

たとえば、私は..

from BeautifulSoup import BeautifulStoneSoup as BSS

..だから私はsoup = BSS(html)代わりに行うことができますBeautifulSoup.BeautifulStoneSoup(html)

または..

from xmpp import XmppClientBase

.. XmppClientBase のみを使用する場合、xmpp 全体をインポートする代わりに

import x as y非常に長いメソッド名をインポートしたい場合、または既存のインポート/変数/クラス/メソッドの破壊を防ぐために使用すると便利です (完全に回避する必要がありますが、常に可能であるとは限りません)。

別のスクリプトから main() 関数を実行したいが、既に main() 関数があるとします。

from my_other_module import main as other_module_main

..自分のmain関数を my_other_module の関数に置き換えないmain

ああ、1 つ-しないでくださいfrom x import *-メソッドがどこから来たのかを簡単に確認できないため、コードが非常に理解しにくくなります ( from x import *; from y import *; my_func()- my_func はどこで定義されていますか?)

いずれの場合も、実行してから実行することができます...import modulenamemodulename.subthing1.subthing2.method("test")

これは純粋に利便性のためのfrom x import y as zものです。コードの読み書きが容易になる場合はいつでも使用してください。

于 2008-10-11T11:27:35.647 に答える
1

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
)

最良の戦略は、これらすべてのインポートをファイルの先頭に保持することです。できればアルファベット順に、最初に import -statements、次に from import -statements に並べます。

ここで、なぜこれが最良の慣習であるかを説明します。

Python には、グローバル名前空間から値が見つからない場合に、メインのインポートから値を探す自動インポートが完全に含まれていた可能性があります。しかし、これは良い考えではありません。その理由を簡単に説明します。単純なインポートよりも実装が複雑であることを除けば、プログラマーは依存関係についてあまり考えず、インポートを調べる以外の方法でインポートした場所を見つける必要があります。

依存関係を見つける必要があることが、人々が "from ... import *" を嫌う理由の 1 つです。ただし、opengl -wrappings など、これを行う必要があるいくつかの悪い例が存在します。

したがって、インポート定義は、プログラムの依存関係を定義するものとして実際に価値があります。それはあなたがそれらをどのように利用すべきかです。それらから、奇妙な関数がどこからインポートされているかをすばやく確認できます。

于 2008-10-15T11:07:41.533 に答える
0

これimport X as Yは、同じモジュール/クラスの実装が異なる場合に役立ちます。

いくつかのネストされたtry..import..except ImportError..importsを使用すると、コードから実装を隠すことができます。lxmletreeインポートの例を参照してください。

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")
于 2008-10-11T10:23:48.567 に答える
0

私は使用していないという事実でジェイソンと一緒です

from X import *

しかし、私の場合 (私は熟練したプログラマーではないので、私のコードはコーディング スタイルにあまり適合していません)、通常、プログラムのバージョン、作成者、エラー メッセージなどのすべての定数を含むファイルをプログラムで作成します。ファイルは単なる定義なので、インポートを行います

from const import *

それは私に多くの時間を節約します。しかし、それはそのインポートを持つ唯一のファイルであり、そのファイル内のすべてが単なる変数宣言であるためです。

クラスと定義を含むファイルでこの種のインポートを行うと便利な場合がありますが、そのコードを読まなければならない場合、関数とクラスを見つけるのに多くの時間を費やします。

于 2010-02-10T13:13:55.180 に答える