Vždy jsem používal tuto metodu:
from sys import argv
a použijte argv
pouze s argv . Existuje však konvence použití tohoto:
import sys
a použití argv pomocí sys.argv
Druhá metoda umožňuje, aby byl kód dokumentován a já (opravdu) jej dodržuji. Ale důvod, proč dávám přednost první metodě, je rychlý, protože importujeme pouze funkci, která je potřebná, spíše než importovat celý modul (který obsahuje více zbytečných funkcí, které python bude ztrácet čas jejich importem). Všimněte si, že potřebuji jen argv a všechny ostatní funkce od sys jsou mi k ničemu.
Takže moje otázky jsou. Opravdu první metoda dělá skript rychlý? Která metoda je preferována nejvíce? Proč?
Komentáře
Odpověď
Import modulu neztrácí nic ; modul je vždy plně importováno (do sys.modules
mapování), takže ať už použijete import sys
nebo from sys import argv
nedělá žádné kurzy.
Jediný rozdíl mezi těmito dvěma výroky je v tom, jaké jméno je vázáno; import sys
váže jméno sys
do modulu (takže sys
-> sys.modules["sys"]
), zatímco from sys import argv
se váže jiný název, argv
, směřující přímo na atribut obsažený uvnitř modulu (takže argv
-> sys.modules["sys"].argv
). Zbytek th e sys
modul stále existuje, ať už použijete cokoli jiného z modulu nebo ne.
Mezi těmito dvěma přístupy také není žádný rozdíl ve výkonu. Ano, sys.argv
musí vyhledat dvě věci; musí vyhledat sys
ve vašem globálním oboru názvů (najde modul) a poté vyhledat atribut argv
. A ano, pomocí from sys import argv
můžete přeskočit vyhledávání atributů, protože na atribut již máte přímý odkaz. Ale prohlášení import
musí tuto práci stále dělat, při importu vyhledá stejný atribut a vy budete muset vždy použít argv
jednou . Pokud byste museli použít argv
tisíckrát ve smyčce, možná by to mohlo změnit, ale v tomto konkrétním případě to opravdu není .
Volba mezi jedním nebo druhým by měla být založena na stylu kódování .
Ve velkém modulu , Určitě použiji import sys
; na dokumentaci kódu záleží a použití sys.argv
někde ve velkém modulu umožňuje mnohem jasnější, na co odkazujete, než jen argv
kdy. / p>
Pokud jediné místo, které používáte argv
, je v "__main__"
bloku pro volání main()
funkce, každopádně použijte from sys import argv
pokud se z toho cítíte šťastnější:
if __name__ == "__main__": from sys import argv main(argv)
I „d stále tam používám import sys
. Všechny věci jsou si rovny (a jsou přesně ve smyslu výkonu a počtu znaků použitých k jeho napsání) , to je pro mě o to jednodušší.
Pokud importujete něco else dohromady, možná do hry vstupuje výkon. Ale pouze pokud použijete konkrétní název v modul mnohokrát , například v kritické smyčce. Vytvoření místního názvu (ve funkci) však bude ještě rychlejší:
import somemodule def somefunction(): localname = somemodule.somefunctionorother while test: # huge, critical loop foo = localname(bar)
Komentáře
- Existuje také situace, kdy máte balíček s dílčími balíčky nebo moduly, který odhaluje atribut jednoho z těchto dílčích balíků / modulů v balíčku nejvyšší úrovně. Použití
from...import
vám umožnípackage.attribute
místopackage.subpackage_or_module.attribute
, což může být užitečné, pokud mít v balíčku logická nebo koncepční seskupení, ale chtějí uživatelům vašeho balíčku usnadnit práci. (Věřím, že něco podobného dělánumpy
.) - V django máte spoustu míst, kde jsou věci jako
from django.core.management.base import BaseCommand
jsou lepší a cokoli jiného (zejménaimport django
) by vedlo k nečitelnému kódu. I když se mi tato odpověď líbí, myslím, že existují některé knihovny (a zejména některé rámce), ve kterých má konvence porušovat holý import.Jako vždy použijte úsudek o tom, co je v dané situaci nejlepší. Ale chyba na straně explicitní (jinými slovy z větší části souhlasím). - @JAB: stále můžete použít
import ... as
k vyhledání balíčku jiný název:import package.subpackage_or_module as shortname
.from parent import sub
dělá v podstatě totéž. -
so wether you use import sys or from sys import argv makes no odds
to se u IDLE zdá být neplatné. jen import modulu neimportuje jeho funkce a mohu jej volat v IDLE shellu pouze < modul >. < function > name - @Suncatcher: přečtěte si moji odpověď v plném rozsahu. Citovaná věta hovoří o tom, kolik se importuje, nikoli o tom, jaké jméno je vázáno. To ‚ je zahrnuto jinde v odpovědi.
Odpověď
Existují dva důvody pro použití import module
namísto from module import function
.
Prvním je jmenný prostor. Import funkce do globálního oboru názvů riskuje kolize názvů.
Druhý není relevantní pro standardní moduly, ale významný pro vaše vlastní moduly, zejména během vývoje. Je to možnost reload()
modul. Zvažte toto:
from module import func ... reload(module) # func still points to the old code
Na druhou stranu
import module ... reload(module) # module.func points to the new code
Pokud jde o rychlost .. .
importujeme pouze funkci, která je potřebná, a ne importujeme celý modul (který obsahuje více zbytečných funkcí, díky nimž bude python ztrácet čas jejich importem)
Ať už importujete modul nebo funkci z modulu, Python provede analýzu celého modulu. V každém případě je modul importován. „Import funkce“ není nic jiného než svázání funkce se jménem. Ve skutečnosti je import module
pro tlumočníka méně práce než from module import func
.
Komentáře
- reload () bylo integrováno v Pythonu 2; to už v případě Pythonu 3 neplatí.
- Myslel jsem, že existují také důsledky týkající se závislostí kruhového importu?
Odpovědět
Používám from import
s, kdykoli to zlepší čitelnost. Například dávám přednost (středníky slouží pouze k úspoře místa zde):
from collections import defaultdict from foomodule import FooBar, FooBaz from twisted.internet.protocol import Factory defaultdict(); FooBar(); FooBaz(); Factory()
místo:
import collections import foomodule import twisted.internet.protocol collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz() twisted.internet.protocol.Factory()
Ten druhý je pro mě těžší číst (a psát), protože obsahuje tolik nadbytečných informací. Je také užitečné vědět předem, jaké části modulu používám.
Mám raději normální import
s, pokud používám hodně krátkých jmen z modulu:
import sys sys.argv; sys.stderr; sys.exit()
Nebo je-li název tak obecný, že mimo jeho jmenný prostor nedává smysl:
import json json.loads(foo) from json import loads loads(foo) # potentially confusing
Komentáře
- Toto je moje oblíbená odpověď. ‚ Výslovnost je lepší než implicitní ‚ někdy v rozporu s čitelností, jednoduchostí a DRY. Zejména při použití rámce jako Django.
Odpověď
Podle mého názoru je použití běžného import
zlepšuje čitelnost. Při kontrole kódu Pythonu rád vidím, odkud daná funkce nebo třída pochází, odkud se používá. Zachraňuje mě to od posouvání do horní části modulu, abych získal tyto informace.
Pokud jde o dlouhé názvy modulů, používám klíčové slovo as
a dávám jim krátké aliasy:
import collections as col import foomodule as foo import twisted.internet.protocol as twip my_dict = col.defaultdict() foo.FooBar() twip_fac = twip.Factory()
Jako výjimku vždy používám notaci from module import something
, když se zabývám __future__
modul. Prostě to nemůžete udělat jiným způsobem, když chcete, aby všechny řetězce byly ve výchozím nastavení v Pythonu 2 unicode, např.
from __future__ import unicode_literals from __future__ import print_function
Komentáře
- Amen! “ import jako “ je výherní kombinace 🙂
Odpověď
Ačkoli import sys
a from sys import agrv
oba importují celý sys
modul, ten používá vázání jmen, takže ke zbytku kódu je přístupný pouze argv
modul.
Pro některé lidi by to byl preferovaný styl, protože zpřístupňuje pouze funkci, kterou jste výslovně uvedli.
Zavádí však potenciální konflikty názvů. Co kdybyste měli jiný modul s názvem argv
? Všimněte si, že můžete také explicitně importovat funkci a přejmenovat ji pomocí from sys import argv as sys_argv
, konvence, která splňuje explicitní import a je méně pravděpodobné, že bude mít jmenný prostor kolize.
Komentáře
- Jak je tedy
if sys_argv:
lepší nežif sys.argv:
? Vím, co znamená druhé tvrzení, nemám tušení, co znamená první forma, aniž bych se vrátil k bizarnímu importu.
Odpověď
Nedávno jsem si tuto otázku položil sám pro sebe. Načasoval jsem různé metody.
požaduje knihovnu
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 library
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
knihovna 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 knihovna
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
Zdá se, že já je malý rozdíl ve výkonu.
Komentáře
- Přidáváte do vyhledávání atributů. Chcete-li
import module
správně porovnat sfrom module import name
, přidejte vyhledání tohoto jména doimport module
případ. Např. přidejte řádeksys.argv
doar
testu atd. Stále bude existovat rozdíl, protože práce je mírně různé, protože se generuje odlišný bytecode a provádějí se různé kódové cesty. - Všimněte si, že tento rozdíl řeším přímo ve své odpovědi; bude rozdíl mezi používáním
import sys
asys.argv
tisíckrát času ve smyčce oprotifrom sys import argv
poté pouze pomocíargv
. Ale ‚ t. U věcí, které uděláte jednou na globální úrovni vašeho modulu, byste se měli skutečně optimalizovat kvůli čitelnosti, nikoli mikroskopickým rozdílům v časování. - Ahhhh! A myslel jsem si, že jsem na něčem! 🙂 Vaši odpověď jsem jen přehnal. Vypadá to, že jsem na toho skočil pistolí. Je dobré být pokořen.
Odpovědět
Podívat se na publikované fragmenty kódu, importovat celé moduly a odkazovat na module.function
je do značné míry standard, alespoň pro standardní moduly. Jedinou výjimkou se zdá být datetime
from datetime import datetime, timedelta
takže můžete říci datetime.now()
spíše než datetime.datetime.now()
.
Pokud vás zajímá výkon, můžete kdykoli říci (například)
argv = sys.argv
a poté proveďte svůj kritický kód výkonu, protože vyhledávání modulů je již hotové. Ačkoli to ale bude fungovat s funkcemi / metodami, většina IDE bude zmatená a nebude například zobrazovat zdrojový odkaz / podpis funkce, když je přiřazena k proměnné.
Odpověď
Chtěl bych jen dodat, že pokud děláte něco jako
from math import sin
(nebo jakákoli jiná vestavěná knihovna jako sys
nebo posix
), pak sin
bude být zahrnuty v dokumentaci k vašemu modulu (tj. když uděláte >>> help(mymodule)
nebo $ pydoc3 mymodule
. Chcete-li tomu zabránit, importujte pomocí:
import math from math import sin as _sin
PS: vestavěná knihovna je knihovna zkompilovaná z kódu C a zahrnutá v Pythonu. argparse
, os
a io
nejsou integrované balíčky
from … import …
v Pythonu