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ísto package.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éna import 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 s from module import name, přidejte vyhledání tohoto jména do import module případ. Např. přidejte řádek sys.argv do ar 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 a sys.argv tisíckrát času ve smyčce oproti from 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

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *