web-dev-qa-db-ja.com

「モジュールのインポート」と「モジュールのインポート機能から」

私はいつもこの方法を使ってきました:

from sys import argv

そして、argvargvだけで使用します。しかし、これを使用する慣習があります:

import sys

sys.argvによるargvの使用

2番目の方法では、コードを自己文書化し、I(本当に)を使用します。しかし、私が最初の方法を好む理由は、モジュール全体をインポートするのではなく、必要な関数のみをインポートしているため高速であるためです(pythonは、インポートに時間を浪費します) 。argvが必要なだけで、sysの他のすべての関数は役に立たないことに注意してください。

だから私の質問です。最初の方法は本当にスクリプトを高速にしますか?どの方法が最も好ましいですか?どうして?

157
Santosh Kumar

モジュールをインポートしても無駄はありませんanything;モジュールは常に完全が(_sys.modules_マッピングに)インポートされるため、_import sys_または_from sys import argv_を使用するかどうかに関係なく、オッズはありません。

2つのステートメントの唯一の違いは、バインドされる名前です。 _import sys_は、名前sysをモジュールにバインドします(so sys-> _sys.modules['sys']_)。一方、_from sys import argv_は、モジュール内に含まれる属性を直接指しているargvをバインドします(so argv) -> _sys.modules['sys'].argv_)。 sysモジュールの残りの部分は、モジュールの他のものを使用するかどうかに関係なく、そのまま残ります。

また、2つのアプローチの間にパフォーマンスの違いはありません。はい、_sys.argv_は2つのことを調べる必要があります。グローバル名前空間でsysを検索し(モジュールを検索)、次に属性argvを検索する必要があります。そして、はい、_from sys import argv_を使用すると、属性への直接参照が既にあるため、属性の検索をスキップできます。ただし、importステートメントは引き続きこの処理を行う必要があります。インポート時に同じ属性を検索します。argvonceを使用するだけで済みます。ループでargvを何千回も使用する必要がある場合、おそらく違いが生じる可能性がありますが、この特定のケースでは実際には違いはありません。

その場合、どちらか一方の選択は、代わりにコーディングスタイルに基づく必要があります。

largeモジュールでは、確かに_import sys_を使用します。コードのドキュメントが重要であり、_sys.argv_を大きなモジュールのどこかに使用すると、argvだけで参照するよりも、参照している内容が明確になります。

argvを使用する唯一の場所が_'__main__'_ブロック内にあり、main()関数を呼び出す場合、それについて幸せだと感じた場合は、必ず_from sys import argv_を使用してください。

_if __name__ == '__main__':
    from sys import argv
    main(argv)
_

私はまだ_import sys_を自分で使用します。すべてが等しい(そして、正確には、パフォーマンスの観点から言えばand書き込みに使用される文字数)、それは私にとっては目に優しいだけです。

何かをインポートする場合elseを一緒に使用すると、おそらくパフォーマンスが発揮されます。ただし、たとえば重要なループで、モジュールで特定の名前を使用する場合のみ何度もを使用します。ただし、ローカル名を(関数内で)作成すると、さらに高速になります。

_ import somemodule

 def somefunction():
      localname = somemodule.somefunctionorother
      while test:
          # huge, critical loop
          foo = localname(bar)
_
184
Martijn Pieters

_import module_ではなく_from module import function_を使用することには、2つの理由があります。

最初は名前空間です。関数をグローバル名前空間にインポートすると、名前の衝突が発生する可能性があります。

2つ目は、標準モジュールに関連するものではありませんが、特に開発中は、独自のモジュールにとって重要です。モジュールのreload()のオプションです。このことを考慮:

_from module import func
...
reload(module)
# func still points to the old code
_

一方

_import module
...
reload(module)
# module.func points to the new code
_

スピードは...

モジュール全体をインポートするのではなく、必要な関数のみをインポートします(これには、pythonがそれらのインポートに時間を浪費する無駄な関数が含まれています)。

モジュールをインポートする場合でも、モジュールから関数をインポートする場合でも、Pythonはモジュール全体を解析します。どちらの方法でもモジュールはインポートされます。「関数のインポート」は、関数を実際、_import module_は_from module import func_よりインタープリターの作業が少ないです。

47
vartec

私の意見では、通常のimportを使用すると読みやすさが向上します。 Pythonコードを確認すると、特定の関数またはクラスがどこから使用されているかがわかります。これにより、モジュールの上部にスクロールしてその情報を取得する手間が省けます。

長いモジュール名については、asキーワードを使用して短いエイリアスを付けます。

import collections as col
import foomodule as foo
import twisted.internet.protocol as twip

my_dict = col.defaultdict()
foo.FooBar()
twip_fac = twip.Factory()

例外として、私は常にfrom module import somethingを扱うときの表記__future__モジュール。 Python 2、.

from __future__ import unicode_literals
from __future__ import print_function
19
golem

私が使う from imports読みやすさを向上させるたびに。たとえば、私は好みます(セミコロンはここでスペースを節約するためだけです):

from collections import defaultdict
from foomodule import FooBar, FooBaz
from twisted.internet.protocol import Factory
defaultdict(); FooBar(); FooBaz(); Factory()

の代わりに:

import collections
import foomodule
import twisted.internet.protocol
collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz()
twisted.internet.protocol.Factory()

後者は冗長な情報を多く含んでいるため、私にとって読み取り(および書き込み)が困難です。また、モジュールのどの部分を使用しているかを事前に知っておくと便利です。

モジュールの短い名前をたくさん使用している場合は、通常のimportsを使用します。

import sys
sys.argv; sys.stderr; sys.exit()

または、名前が汎用的すぎて名前空間の外では意味をなさない場合:

import json
json.loads(foo)

from json import loads
loads(foo)  # potentially confusing
19
user76704

import sysfrom sys import agrvはどちらもsysモジュール全体をインポートしますが、後者は名前バインディングを使用するため、残りのコードはargvモジュールのみにアクセスできます。

一部の人々にとっては、これはあなたが明示的に述べた機能にアクセスできるようにするだけなので、これが好ましいスタイルです。

ただし、名前の競合が発生する可能性があります。 argvという名前の別のモジュールがある場合はどうなりますか?関数を明示的にインポートしてfrom sys import argv as sys_argvで名前を変更することもできます。これは、明示的なインポートに対応し、名前空間の衝突を起こしにくい規則です。

4
Duncan

私は最近この質問を自分に問いかけました。さまざまな方法で時間を計った。

ライブラリをリクエストする

def r():
    import requests
    return 'hello'
timeit r() # output: 1000000 loops, best of 3: 1.55 µs per loop

def rg():
    from requests import get
    return 'hello'
timeit rg() # output: 100000 loops, best of 3: 2.53 µs per loop

beautifulsoupライブラリ

def bs():
    import bs4
    return 'hello' 
timeit bs() # output: 1000000 loops, best of 3: 1.53 µs per loop

def be():
    from bs4 import BeautifulSoup
    return 'hello'
timeit be() # output: 100000 loops, best of 3: 2.59 µs per loop

jsonライブラリ

def js():
    import json
    return 'hello'
timeit js() # output: 1000000 loops, best of 3: 1.53 µs per loop

def jl():
    from json import loads
    return 'hello'
timeit jl() # output: 100000 loops, best of 3: 2.56 µs per loop

sysライブラリ

def s():
    import sys
    return 'hello'
timeit s() # output: 1000000 loops, best of 3: 1.55 µs per loop

def ar():
    from sys import argv
    return 'hello'
timeit ar() # output: 100000 loops, best of 3: 2.87 µs per loop

あるパフォーマンスにわずかな違いがあるように思えます。

1
tmthyjames