Ik heb altijd deze methode gebruikt:
from sys import argv
en gebruik argv
met slechts argv . Maar er is een conventie om dit te gebruiken:
import sys
en het gebruik van argv door sys.argv
De tweede methode zorgt ervoor dat de code zelf gedocumenteerd is en ik (echt) houd me eraan. Maar de reden dat ik de voorkeur geef aan de eerste methode is dat deze snel is omdat we alleen de functie importeren die nodig is in plaats van de hele module te importeren (die meer nutteloze functies bevat die Python tijd zal verspillen met het importeren ervan). Merk op dat ik alleen argv nodig heb en alle andere functies van sys zijn nutteloos voor mij.
Dus mijn vragen zijn. Maakt de eerste methode het script echt snel? Welke methode heeft de meeste voorkeur? Waarom?
Reacties
Answer
Het importeren van de module “verspilt niets ; de module is altijd volledig geïmporteerd (in de sys.modules
mapping), dus of je nu import sys
of from sys import argv
maakt geen enkele kans.
Het enige verschil tussen de twee uitspraken is welke naam gebonden is; import sys
bindt de naam sys
naar de module (dus sys
-> sys.modules["sys"]
), terwijl from sys import argv
bindt een andere naam, argv
, die rechtstreeks naar het kenmerk in de module wijst (dus argv
-> sys.modules["sys"].argv
). De rest van th De sys
module is er nog, of je nu iets anders uit de module gebruikt of niet.
Er is ook geen prestatieverschil tussen de twee benaderingen. Ja, sys.argv
moet twee dingen opzoeken; het moet sys
opzoeken in je globale naamruimte (vindt de module), en dan het attribuut argv
opzoeken. En ja, door from sys import argv
te gebruiken, kunt u het opzoeken van het attribuut overslaan, aangezien u al een directe verwijzing naar het attribuut heeft. Maar de import
-instructie moet dat werk nog steeds doen, het zoekt hetzelfde attribuut op bij het importeren, en je “zult alleen argv
een keer . Als je argv
duizenden keren in een lus zou moeten gebruiken, zou het misschien een verschil kunnen maken, maar in dit specifieke geval doet het echt niet .
De keuze tussen de een of de ander moet in plaats daarvan gebaseerd zijn op coderingsstijl .
In een grote module , Ik “zou zeker import sys
gebruiken; codedocumentatie is van belang, en als je sys.argv
ergens in een grote module gebruikt, wordt het veel duidelijker waarnaar je verwijst dan alleen argv
ooit zou doen.
Als de enige plaats die u gebruikt argv
zich in een "__main__"
blok bevindt om een functie, gebruik in elk geval from sys import argv
als je je daar gelukkiger bij voelt:
if __name__ == "__main__": from sys import argv main(argv)
I “d gebruik nog steeds import sys
daar zelf. Alle dingen zijn gelijk (en ze zijn, precies, in termen van prestaties en aantal tekens gebruikt om het te schrijven) , dat is gewoon makkelijker voor het oog voor mij.
Als u iets anders helemaal importeert, komt de uitvoering misschien in het spel. Maar alleen als u een specifieke naam in een module vele malen , in een kritieke lus bijvoorbeeld. Maar dan gaat het maken van een lokale naam (binnen een functie) nog sneller:
import somemodule def somefunction(): localname = somemodule.somefunctionorother while test: # huge, critical loop foo = localname(bar)
Opmerkingen
- Er is ook de situatie dat je een pakket hebt met subpakketten of modules die een attribuut van een van die subpakketten / modules in het pakket op het hoogste niveau blootlegt. Door
from...import
te gebruiken, kun jepackage.attribute
doen in plaats vanpackage.subpackage_or_module.attribute
, wat handig kan zijn als je hebben logische of conceptuele groeperingen binnen het pakket, maar willen de zaken een beetje handiger maken voor gebruikers van uw pakket. (numpy
doet zoiets, geloof ik.) - In django heb je talloze plekken waar dingen als
from django.core.management.base import BaseCommand
zijn beter, en al het andere (vooralimport django
) zou tot onleesbare code leiden. Dus hoewel ik dit antwoord leuk vind, denk ik dat er enkele bibliotheken zijn (en vooral enkele frameworks) waarin de conventie is om de kale import te schenden.Gebruik zoals altijd uw oordeel over wat het beste is in een bepaalde situatie. Maar vergis je aan de kant van expliciet (met andere woorden, ik ben het grotendeels eens). - @JAB: je kunt nog steeds
import ... as
gebruiken om het pakket te vinden een andere naam:import package.subpackage_or_module as shortname
.from parent import sub
doet in wezen hetzelfde. -
so wether you use import sys or from sys import argv makes no odds
dit lijkt niet het geval te zijn met IDLE. alleen het importeren van de module importeert zijn functies niet en ik kan het alleen in IDLE-shell aanroepen met < module >. < functie > naam - @Suncatcher: lees mijn antwoord volledig. De zin die u citeert, vertelt hoeveel er wordt geïmporteerd, niet welke naam is gebonden. Dat ‘ wordt elders in het antwoord behandeld.
Antwoord
Er zijn twee redenen om import module
te gebruiken in plaats van from module import function
.
De eerste is de naamruimte. Het importeren van een functie in de globale naamruimte riskeert naambotsingen.
Ten tweede is “niet zo relevant voor standaardmodules, maar significant voor uw eigen modules, vooral tijdens de ontwikkeling. Het is de optie om reload()
een module. Overweeg dit:
from module import func ... reload(module) # func still points to the old code
Anderzijds
import module ... reload(module) # module.func points to the new code
Wat betreft snelheid .. .
we importeren alleen de functie die nodig is in plaats van de hele module te importeren (die meer nutteloze functies bevat die Python tijd zal verspillen met het importeren ervan)
Of je nu een module importeert of een functie uit een module importeert, Python zal de hele module ontleden. Hoe dan ook, de module wordt geïmporteerd. “Een functie importeren” is niets meer dan de functie aan een naam binden. In feite is import module
minder werk voor een tolk dan from module import func
.
Opmerkingen
- reload () was ingebouwd in Python 2; dat is niet langer het geval voor Python 3.
- Ik dacht dat er ook implicaties waren die te maken hadden met afhankelijkheden van circulaire import?
Antwoord
Ik gebruik from import
s wanneer het de leesbaarheid verbetert. Ik geef bijvoorbeeld de voorkeur aan (puntkommas zijn hier alleen om ruimte te besparen):
from collections import defaultdict from foomodule import FooBar, FooBaz from twisted.internet.protocol import Factory defaultdict(); FooBar(); FooBaz(); Factory()
in plaats van:
import collections import foomodule import twisted.internet.protocol collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz() twisted.internet.protocol.Factory()
Dit laatste is voor mij moeilijker te lezen (en te schrijven) omdat het zoveel overtollige informatie bevat. Het is ook handig om van tevoren te weten welke delen van een module ik “gebruik.
Ik geef de voorkeur aan gewone import
s als ik veel gebruik van korte namen uit een module:
import sys sys.argv; sys.stderr; sys.exit()
Of als een naam zo algemeen is dat hij “buiten de naamruimte” geen betekenis heeft:
import json json.loads(foo) from json import loads loads(foo) # potentially confusing
Reacties
- Dit is mijn favoriete antwoord. ‘ Expliciet is beter dan impliciet ‘ conflicteert soms met leesbaarheid, eenvoud en DROOG. Vooral als je een framework zoals Django gebruikt.
Answer
Naar mijn mening gebruik ik gewoon import
verbetert de leesbaarheid. Bij het bekijken van Python-code vind ik het leuk om te zien waar de gegeven functie of klasse vandaan komt, precies waar deze wordt gebruikt. Het bespaart me om naar de bovenkant van de module te scrollen om die info te krijgen.
Wat betreft de lange modulenamen gebruik ik gewoon het as
trefwoord en geef ze kort aliassen:
import collections as col import foomodule as foo import twisted.internet.protocol as twip my_dict = col.defaultdict() foo.FooBar() twip_fac = twip.Factory()
Als uitzondering gebruik ik altijd de from module import something
-notatie wanneer ik te maken heb met de __future__
module. Je kunt het gewoon “niet op een andere manier doen als je wilt dat alle strings standaard unicode zijn in Python 2, bijv.
from __future__ import unicode_literals from __future__ import print_function
Reacties
- Amen! ” importeren als ” is een winnende combinatie 🙂
Antwoord
Hoewel import sys
en from sys import agrv
beide importeren de volledige sys
module, de laatste gebruikt name binding dus alleen de argv
module is toegankelijk voor de rest van de code.
Voor sommige mensen zou dit de voorkeursstijl zijn, aangezien het alleen de functie toegankelijk maakt die je expliciet vermeldt.
Het introduceert echter mogelijke naamconflicten. Wat als je een andere module had met de naam argv
? Let op: u kunt de functie ook expliciet importeren en hernoemen met from sys import argv as sys_argv
, een conventie die voldoet aan de expliciete import en het is minder waarschijnlijk dat u naamruimte geeft botsingen.
Reacties
- Dus hoe is
if sys_argv:
beter danif sys.argv:
? Ik weet wat de tweede verklaring betekent, ik heb geen idee wat de eerste vorm betekent zonder terug te gaan naar de bizarre betekenis.
Antwoord
Ik heb deze vraag onlangs aan mezelf gesteld. Ik heb de verschillende methoden getimed.
vraagt bibliotheek
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 bibliotheek
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-bibliotheek
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-bibliotheek
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
Het lijkt erop dat mij dat er een klein verschil in prestatie is.
Opmerkingen
- U voegt een attribuutzoekopdracht toe. Om
import module
te vergelijken metfrom module import name
, voegt die naamzoekopdracht toe aan deimport module
geval. Bijv. voeg de regelsys.argv
toe aan dear
-test, enz. Er zal nog steeds een verschil zijn, omdat het verrichte werk enigszins anders, aangezien er verschillende bytecodes worden gegenereerd en verschillende codepaden worden uitgevoerd. - Merk op dat ik dat verschil direct in mijn antwoord behandel; er zal een verschil zijn tussen
import sys
ensys.argv
duizenden keren in een lus gebruiken versusfrom sys import argv
gebruik dan alleenargv
. Maar je doet ‘ t. Voor dingen die je slechts een keer doet op het globale niveau van je module, zou je echt moeten optimaliseren voor leesbaarheid, niet voor microscopische verschillen in timing. - Ahhhh! En ik dacht dat ik iets van plan was! 🙂 Ik heb alleen je antwoord afgetapt. Het lijkt erop dat ik daar met het pistool op heb gesprongen. Het voelt goed om vernederd te worden.
Answer
Gepubliceerde codefragmenten bekijken, hele modules importeren en verwijzen naar module.function
is vrijwel de standaard, althans voor standaardmodules. De enige uitzondering lijkt datetime
from datetime import datetime, timedelta
te zijn, dus je kunt datetime.now()
.
Als u zich zorgen maakt over de prestaties, kunt u altijd zeggen (bijvoorbeeld)
argv = sys.argv
en voer vervolgens uw prestatie-kritieke code uit aangezien het opzoeken van de module al is voltooid. Hoewel dit zal werken met functies / methoden, zullen de meeste IDEs in de war raken en (bijvoorbeeld) geen bronlink / handtekening voor de functie weergeven wanneer deze aan een variabele is toegewezen.
Antwoord
Ik wil dat gewoon toevoegen als je zoiets doet
from math import sin
(of een andere ingebouwde bibliotheek zoals sys
of posix
), dan zal sin
worden opgenomen in de documentatie voor uw module (dwz wanneer u >>> help(mymodule)
of $ pydoc3 mymodule
doet. Om dit te voorkomen, importeert u met:
import math from math import sin as _sin
PS: een ingebouwde bibliotheek is een bibliotheek die is gecompileerd uit C-code en wordt meegeleverd met Python. argparse
, os
en io
zijn geen ingebouwde pakketten
from … import …
syntaxis in Python