この点についてはあまり明確ではありません。独自のモジュールである.pyファイルがたくさんあるとします。
各.pyファイルがそのクラスを使用するときに他のファイルをインポートする必要があるのはなぜですか?それともそうですか?他の言語(Javaなど)は、同じディレクトリ内のクラス/ファイルを参照するときにインポートする必要がないことを確信していたからです。私は間違っているかもしれません。
この点についてはあまり明確ではありません。独自のモジュールである.pyファイルがたくさんあるとします。
各.pyファイルがそのクラスを使用するときに他のファイルをインポートする必要があるのはなぜですか?それともそうですか?他の言語(Javaなど)は、同じディレクトリ内のクラス/ファイルを参照するときにインポートする必要がないことを確信していたからです。私は間違っているかもしれません。
回答:
簡単に言えば、それはそれが設計された方法です。反例としてJavaについて説明しましたが、Java言語の設計者はクラスローディングをいくぶん暗黙的にしたかったので、スローする前に同じディレクトリをチェックしましたClassNotFound
。それ以外では、Pythonと同じように、資格を得る必要があります。
Tom Andersonが言ったように、CはPythonと同じことを行い、それはコンパイルされた言語です。おそらく、言語の解釈された性質は、最終的な決定(パフォーマンス、明示性など)に関係していましたが、最終的には開発者次第です。
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
、数学関数またはインタプリタ内の変数の場合、環境がうまく機能しません。
あなたがこのコードを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の哲学に適合します。自動的にインポートするよりも、明示的にモジュールをインポートする方がよいと考えています。エラーメッセージの問題は、決定を左右する要因です。
一部のユーザーは、暗黙的なインポートには実行時のコストが大きいと示唆しています。私はそうは思いません。何が起こるかは次のようなものです:
暗黙的なモジュールの読み込みをサポートするために、次のことができます。
import foo
モジュールを初めて使用するときは、最初に他の辞書を検索する必要があるため、少し時間がかかります。しかし、それは初めてのことであり、プログラム全体の実行時間の点で重要であってはなりません。
変数名にスペルミスがある場合は、かなりのコストがかかります。それらが発生すると、Pythonはモジュールを見つけるためにディスクを読み取る時間を無駄にします。しかし、それが起こった場合、プログラムはとにかくトレースバックで死にかけようとしており、パフォーマンスは大きな問題ではありません。
PythonとJavaの間にはいくつかの重要な違いがあります。Javaには「ファイルごとに1つのクラス」ルールがありますが、Pythonにはありません。また、Pythonのすべてがクラスであるとは限りません。
そのため、モジュールはクラス、関数、そして単純な古い変数を持つことができます-通常はすべて何らかの方法で関連しています(のランダム関数random
、の数学ルーチンmath
、の文字列定数string
など)。
特定のモジュールからクラス/関数/変数にアクセスする場合は、最初にそれをインポートする必要があります。
なぜこれが良いことなのですか?
math.sin
、名前を使用できます(独自のsin
関数を使用できます)。Pythonの最も重要な概念の1つは、名前空間の概念です(import this
プロンプトでしばらくしてから、他の概念を確認してください)。名前空間は他の言語にも存在することは知っていますが、Pythonでは現在の名前空間にのみアクセスできます。これは、現在のモジュールで定義されているものです。他の識別子にアクセスするには、それらを現在の名前空間にインポートする必要があります。それらを含むモジュール(import foo
構文)または名前自体(from foo import bar
)をインポートします。