Python:「インポート」を使用する意味は何ですか?


8

この点についてはあまり明確ではありません。独自のモジュールである.pyファイルがたくさんあるとします。

各.pyファイルがそのクラスを使用するときに他のファイルをインポートする必要があるのはなぜですか?それともそうですか?他の言語(Javaなど)は、同じディレクトリ内のクラス/ファイルを参照するときにインポートする必要がないことを確信していたからです。私は間違っているかもしれません。

回答:


8

簡単に言えば、それはそれが設計された方法です。反例としてJavaについて説明しましたが、Java言語の設計者はクラスローディングをいくぶん暗黙的にしたかったので、スローする前に同じディレクトリをチェックしましたClassNotFound。それ以外では、Pythonと同じように、資格を得る必要があります。

Tom Andersonが言ったように、CはPythonと同じことを行い、それはコンパイルされた言語です。おそらく、言語の解釈された性質は、最終的な決定(パフォーマンス、明示性など)に関係していましたが、最終的には開発者次第です。


「それが設計された方法」がこの質問への答えであるかどうかはわかりません。
Winston Ewert、2011

2
-1:私はよくのPythonを知らないが、私の理解では、ということである持っている Pythonでそれに何かを使用するパッケージをインポートします。Javaでは、技術的にimportステートメントを使用する必要はありません。クラスの完全修飾名などを他のパッケージに書き出すだけです。
compman 2011

1
資格とは、オブジェクト(クラス、関数など)へのパスを解決することです。インポートによって行われるのか構文修飾子によって行われるのかは関係ありません。
Michael K

3

pythonが解釈されるため、インポートしたすべてのものがプロンプトで使用可能になります。Java(およびC ++)には、使用される関数のみを検索して含めることができるコンパイルおよびリンク手順があります。

すべてが自動的にインポートされた場合、何千もの関数と変数が存在し、衝突することなく何かを入力することは不可能です。

編集:わかりました。コンパイルと解釈だけではありません。Pythonは「バッテリーを含む」言語として意図されています-ほとんどすべてを行うために利用可能なライブラリがあります。それらのごく一部しか使用しないため、必要なものだけを含めるようにそれらを編成する方法が必要です。

ライブラリ全体をインポートしてJavaのような完全修飾名を保持するか、特定の関数(またはすべての関数)をローカル名前空間にインポートできるため、構文からのインポートは賢いです

>>>import math
>>> math.sin(0)  #no confusion with any other 'sin'

>>> from math import sin  # or import *
>>> sin(0) # makes equations with sin shorter and simpler

2番目の理由は、Pythonなどの動的言語では特に重要です。変数を使用する前に変数を定義する必要がないためsin、数学関数またはインタプリタ内の変数の場合、環境がうまく機能しません。


わかりません... newbについて説明してもらえますか?:(
チャックテスタ

:非常に簡単な言葉で、このブログの記事は合計それを- @ChuckTestaするためには、完全にこの答えでdiscusssed違いを理解し、あなたがコンパイルされ、解釈された言語の違いを理解する必要がありblog.julipedia.org/2004/07/...
ボブ

8
違いは、インタープリタとコンパイル済みの違いにはまったく関係ありません。あなたはPythonコンパイラを書くことができ、Pythonインタプリタとまったく同じように動作する必要があります。違いは、Javaの設計者が(たとえば)他のファイルからクラスの暗黙的なロードを追加することを決定し、Pythonの設計者は追加しなかったことです。Cはコンパイルされますが、基本的にはPythonと同じルールがあります。ヘッダーを#includeして適切なライブラリをリンクしない限り、別のファイルの関数を使用することはできません。
トムアンダーソン、

2
要点は有効です。暗黙的なクラスの読み込みは、インタープリター型言語では実行時に大きなコストがかかります
Simon Bergot

1
@サイモン、なぜそれは大きなランタイムコストがあるのでしょうか?
Winston Ewert、2011

1

あなたがこのコードをPythonで持っていると想像してください:

foo = MyObject()
fo.bar()

明らかに、タイプミスがあり、そうであったfoはずfooです。今のPythonは言う:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'fo' is not defined

しかし、暗黙的なクラスローディングでは、それは言うかもしれません:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named fo

混乱するでしょう。さらに悪いことに、たまたまモジュールの名前である変数名のスペルを間違えた場合、そのモジュールを変数であるかのように処理しようとすると、さらに混乱するエラーが発生します。Pythonは、何かがクラス名であるか、オブジェクトであるかを判別できません。

一方、Javaは、特定の識別子がクラスを指しているのか、それ以外の何かを指しているのかを構文から判断できると思います。したがって、適切なエラーメッセージが表示されても問題はありません。

全体として、暗黙的ではなく明示的であるというPythonの哲学に適合します。自動的にインポートするよりも、明示的にモジュールをインポートする方がよいと考えています。エラーメッセージの問題は、決定を左右する要因です。

一部のユーザーは、暗黙的なインポートには実行時のコストが大きいと示唆しています。私はそうは思いません。何が起こるかは次のようなものです:

  1. 「foo」という名前で呼び出されたLOAD_GLOBALオペコード
  2. 「foo」がチェックされたグローバルディクショナリ
  3. "foo"がチェックされた組み込み辞書
  4. fooが見つかった場合は、グローバルに保存して続行します
  5. fooが見つからない場合、NameErrorを送出します

暗黙的なモジュールの読み込みをサポートするために、次のことができます。

  1. 「foo」という名前で呼び出されたLOAD_GLOBALオペコード
  2. 「foo」がチェックされたグローバルディクショナリ
  3. "foo"がチェックされた組み込み辞書
  4. 上記が失敗した場合は、 import foo
  5. fooが見つかった場合は、グローバルに保存して続行します
  6. fooが見つからない場合、NameErrorを送出します

モジュールを初めて使用するときは、最初に他の辞書を検索する必要があるため、少し時間がかかります。しかし、それは初めてのことであり、プログラム全体の実行時間の点で重要であってはなりません。

変数名にスペルミスがある場合は、かなりのコストがかかります。それらが発生すると、Pythonはモジュールを見つけるためにディスクを読み取る時間を無駄にします。しかし、それが起こった場合、プログラムはとにかくトレースバックで死にかけようとしており、パフォーマンスは大きな問題ではありません。


1

PythonとJavaの間にはいくつかの重要な違いがあります。Javaには「ファイルごとに1つのクラス」ルールがありますが、Pythonにはありません。また、Pythonのすべてがクラスであるとは限りません。

そのため、モジュールはクラス、関数、そして単純な古い変数を持つことができます-通常はすべて何らかの方法で関連しています(のランダム関数random、の数学ルーチンmath、の文字列定数stringなど)。

特定のモジュールからクラス/関数/変数にアクセスする場合は、最初にそれをインポートする必要があります。

なぜこれが良いことなのですか?

  • モジュールの名前空間をクリーンに保ちます(決して使用しない名前で乱雑になりません)
  • 問題が発生したときに適切なモジュールに戻るのが簡単
  • 名前が使用されているためにエラーが発生したり、すでに使用されている名前を壊したりすることなくmath.sin、名前を使用できます(独自のsin関数を使用できます)。
  • プログラムの構造を明確にするのに役立ちます。

1

Pythonの最も重要な概念の1つは、名前空間の概念です(import thisプロンプトでしばらくしてから、他の概念を確認してください)。名前空間は他の言語にも存在することは知っていますが、Pythonでは現在の名前空間にのみアクセスできます。これは、現在のモジュールで定義されているものです。他の識別子にアクセスするには、それらを現在の名前空間にインポートする必要があります。それらを含むモジュール(import foo構文)または名前自体(from foo import bar)をインポートします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.