526

import module使用するのが最適かどうかについての包括的なガイドを見つけようとしましたfrom module import。Pythonを使い始めたばかりで、ベストプラクティスを念頭に置いて始めようとしています。

基本的に、私は誰かが彼らの経験を共有できるかどうか、他の開発者がどのような好みを持っているか、そして将来の落とし穴を避けるための最良の方法は何であるかを望んでいました。

4

21 に答える 21

573

import moduleとの違いfrom module import fooは主に主観的なものです。一番気に入ったものを選び、一貫して使用してください。ここでは、決定するのに役立ついくつかのポイントを示します。

import module

  • 長所:
    • importステートメントのメンテナンスが少なくなります。モジュールの別のアイテムの使用を開始するために追加のインポートを追加する必要はありません
  • 短所:
    • コードを入力module.fooするのは面倒で冗長な場合があります (退屈は、import module as mo次に入力することで最小限に抑えることができますmo.foo) 。

from module import foo

  • 長所:
    • 使用するタイピングが少ないfoo
    • モジュールのどの項目にアクセスできるかをより詳細に制御
  • 短所:
    • モジュールから新しいアイテムを使用するには、importステートメントを更新する必要があります
    • についてのコンテキストが失われますfoo。たとえばceil()math.ceil()

どちらの方法でもかまいませんが、使用しないでくださいfrom module import *

合理的な大規模なコード セットの場合、import *それをモジュールに固定する可能性が高い場合は、削除できません。これは、コードで使用されているアイテムが「モジュール」から来ているかどうかを判断するのが難しいためです。これにより、もう使用していないと思われるポイントに簡単に到達できますimportが、それを確認することは非常に困難です。

于 2009-04-02T16:52:11.633 に答える
233

モジュールへの書き込みに関連する、言及されていない別の詳細がここにあります。確かに、これはあまり一般的ではないかもしれませんが、時々必要になりました。

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"

私の設定はamodule内の名前「バー」に影響を与えただけで、モジュールオブジェクトに「到達」してその.barbarafoobar

于 2013-10-04T16:10:12.673 に答える
105

多くの人がimportvsについてすでに説明しimport fromていますが、内部で何が起こっているのか、そしてそれが変化するすべての場所がどこにあるのかについて、もう少し説明したいと思います。


import foo:

をインポートfooし、現在の名前空間でそのモジュールへの参照を作成します。次に、モジュール内から特定の属性またはメソッドにアクセスするための完全なモジュール パスを定義する必要があります。

たとえばfoo.bar、そうではありませんbar

from foo import bar:

をインポートfooし、リストされたすべてのメンバーへの参照を作成します ( bar)。変数を設定しませんfoo

例: barbut not bazorfoo.baz

from foo import *:

をインポートfooし、現在の名前空間でそのモジュールによって定義されたすべてのパブリック オブジェクトへの参照を作成します (存在する__all__場合は にリストされて__all__いるすべて、存在しない場合は で始まらないすべて_)。変数を設定しませんfoo

たとえばbarand であり、 orではありbazません。_quxfoo._qux


それでは、いつ行うか見てみましょうimport X.Y:

>>> import sys
>>> import os.path

sys.modules名前osと で確認してください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'>

およびを使用して名前空間のディクテーションを確認globals()します。locals()osos.path

>>> 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
>>>

from locals() 名前空間を削除すると、sys.modules に存在する場合と同様osにアクセスできなくなります。osos.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

および で確認sys.modulesします。osos.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

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'
>>>

pathではなく名前を使用してアクセスできますos.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'
>>>
于 2014-02-04T08:40:54.420 に答える
44

両方の方法がサポートされているのには理由があります。一方が他方よりも適切な場合があります。

  • import module: モジュールの多くのビットを使用している場合に便利です。欠点は、各参照をモジュール名で修飾する必要があることです。

  • from module import ...: インポートされたアイテムがモジュール名のプレフィックスなしで直接使用できるのは素晴らしいことです。欠点は、使用するすべてのものをリストする必要があることと、何かがどこから来たのかがコードで明確でないことです。

どちらを使用するかは、どちらがコードを明確にして読みやすくするかに依存し、個人の好みと少なからず関係があります。import moduleコードでは、オブジェクトまたは関数がどこから来たのかが非常に明確であるため、私は一般的に傾いています。from module import ...コードでオブジェクト/関数を頻繁に使用しているときに使用します。

于 2009-04-02T16:50:35.100 に答える
36

個人的にいつも使っている

from package.subpackage.subsubpackage import module

そして、次のようにすべてにアクセスします

module.function
module.modulevar

その理由は、呼び出しが短いと同時に、各ルーチンのモジュール名前空間を明確に定義しているためです。これは、ソース内の特定のモジュールの使用法を検索する必要がある場合に非常に役立ちます。

言うまでもなく、名前空間を汚染し、特定の関数がどこから来たのか (どのモジュールから) がわからないため、 import * を使用しないでください。

もちろん、次のように、2 つの異なるパッケージ内の 2 つの異なるモジュールに同じモジュール名を使用すると、問題が発生する可能性があります。

from package1.subpackage import module
from package2.subpackage import module

この場合、もちろん問題に遭遇しますが、パッケージのレイアウトに欠陥があるという強いヒントがあり、再考する必要があります。

于 2009-04-02T17:03:54.257 に答える
17
import module

モジュールから多くの機能を使用する場合に最適です。

from module import function

のみが必要な場合に、モジュールのすべての関数と型でグローバル名前空間を汚染するのを避けたい場合に最適ですfunction

于 2009-04-02T16:52:49.837 に答える
12

これら 2 つの方法の間にもう 1 つの微妙な違いがあることを発見しました。

モジュールfooが次のインポートを使用する場合:

from itertools import count

その場合、モジュールbarは誤ってではなく でcount定義されているかのように使用される可能性があります。fooitertools

import foo
foo.count()

使用する場合foo:

import itertools

間違いはまだ可能性がありますが、発生する可能性は低くなります。barする必要がある:

import foo
foo.itertools.count()

これは私にいくつかの問題を引き起こしました。モジュールを定義していないモジュールから誤って例外をインポートし、他のモジュールからのみインポートしたモジュールがありました(を使用from module import SomeException)。インポートが不要になり削除されたとき、問題のモジュールは壊れていました。

于 2013-05-22T09:56:25.207 に答える
11

言及されていない別の違いがあります。これはhttp://docs.python.org/2/tutorial/modules.htmlから逐語的にコピーされたものです

使用時のご注意

from package import item

項目は、パッケージのサブモジュール (またはサブパッケージ)、または関数、クラス、変数など、パッケージで定義された他の名前のいずれかです。import ステートメントは、最初に項目がパッケージで定義されているかどうかをテストします。そうでない場合は、それがモジュールであると想定し、ロードを試みます。見つからない場合は、ImportError 例外が発生します。

逆に、次のような構文を使用する場合

import item.subitem.subsubitem

最後のアイテムを除く各アイテムはパッケージである必要があります。最後の項目はモジュールまたはパッケージにすることができますが、前の項目で定義されたクラス、関数、または変数にすることはできません。

于 2014-01-16T19:05:39.693 に答える
6
import package
import module

ではimport、トークンはモジュール (Python コマンドを含むファイル) またはパッケージ (sys.pathファイルを含む 内のフォルダー) である必要があります__init__.py

サブパッケージがある場合:

import package1.package2.package
import package1.package2.module

フォルダー (パッケージ) またはファイル (モジュール) の要件は同じですが、フォルダーまたはファイルは 内package2にある必要がありpackage1、 と の両方package1にファイルpackage2が含まれている必要があり__init__.pyます。https://docs.python.org/2/tutorial/modules.html

fromインポートのスタイル:

from package1.package2 import package
from package1.package2 import module

パッケージまたはモジュールは、importステートメントを含むファイルの名前空間に、 ではなくmodule(またはpackage)として入りますpackage1.package2.module。より便利な名前にいつでもバインドできます。

a = big_package_name.subpackage.even_longer_subpackage_name.function

from特定の関数または変数に名前を付けることができるのは、インポートのスタイルのみです。

from package3.module import some_function

許可されていますが、

import package3.module.some_function 

許可されていません。

于 2015-02-22T05:37:51.653 に答える
5

人々が言っ​​たことに付け加えるとfrom x import *、名前の由来がわかりにくくなるだけでなく、Pylint などのコード チェッカーが無効になります。これらの名前は未定義の変数として報告されます。

于 2009-04-02T17:46:08.400 に答える
4

これに対する私自身の答えは、まず、使用するモジュールの数に大きく依存します。1 つまたは 2 つしか使用しない場合は、from...を使用することがよくあります。importファイルの残りの部分でキーストロークが少なくなるためです。しかし、多くの異なるモジュールを使用する場合は、importこれは、各モジュール参照が自己文書化されていることを意味するためです。探し回らなくても、各シンボルがどこから来ているかを確認できます。

通常、私は単純なインポートの自己文書化スタイルを好み、インポートするモジュールが 1 つしかない場合でも、モジュール名を入力する必要がある回数が 10 から 20 を超えたときにのみ from.. import に変更します。

于 2009-04-02T17:53:14.763 に答える
2

Jan Wrobelが言及しているように、さまざまなインポートの 1 つの側面は、インポートがどのように開示されるかです。

モジュールmymath

from math import gcd
...

mymathの使用:

import mymath
mymath.gcd(30, 42)  # will work though maybe not expected

gcdのユーザーに開示しないように、内部使用のみを目的としてインポートした場合mymath、これは不便な場合があります。私はこれをかなり頻繁に持っており、ほとんどの場合、「モジュールをきれいに保ちたい」と思っています。

代わりに使用することでこれをもう少しあいまいにするというJan Wrobelの提案とは別にimport math、私は先頭のアンダースコアを使用してインポートを開示から隠し始めました。

# for instance...
from math import gcd as _gcd
# or...
import math as _math

大規模なプロジェクトでは、この「ベスト プラクティス」により、後続のインポートで何を公開し、何を公開しないかを正確に制御できます。これにより、モジュールがきれいに保たれ、プロジェクトの特定のサイズで元が取れます。

于 2020-04-13T04:22:53.100 に答える
1

モジュールのインポート - モジュールから別のものを取得するための追加の作業は必要ありません。冗長な入力などの欠点があります

モジュールのインポート元 - 入力を減らし、モジュールのどのアイテムにアクセスできるかをより詳細に制御します。モジュールから新しいアイテムを使用するには、インポート ステートメントを更新する必要があります。

于 2016-01-20T05:51:40.553 に答える