Jeg har alltid brukt denne metoden:
from sys import argv
og bruk argv
med bare argv . Men det er en konvensjon å bruke dette:
import sys
og bruke argv av sys.argv
Den andre metoden gjør koden selvdokumentert og jeg (virkelig) følger den. Men grunnen til at jeg foretrekker den første metoden er at den er rask fordi vi bare importerer funksjonen som trengs i stedet for å importere hele modulen (som inneholder flere ubrukelige funksjoner som python vil kaste bort tid på å importere dem). Merk at jeg bare trenger argv og alle andre funksjoner fra sys er ubrukelige for meg.
Så spørsmålene mine er. Gjør den første metoden virkelig skriptet raskt? Hvilken metode foretrekkes mest? Hvorfor?
Kommentarer
Svar
Import av modulen kaster ikke bort noe ; modulen er alltid fullstendig importert (til sys.modules
kartleggingen), så uansett om du bruker import sys
eller from sys import argv
gir ingen odds.
Den eneste forskjellen mellom de to utsagnene er hva navnet er bundet; import sys
binder navnet sys
til modulen (så sys
-> sys.modules["sys"]
), mens from sys import argv
binder et annet navn, argv
, som peker rett på attributtet inne i modulen (så argv
-> sys.modules["sys"].argv
). Resten av th e sys
-modulen er fremdeles der, enten du bruker noe annet fra modulen eller ikke.
Det er heller ingen ytelsesforskjell mellom de to tilnærmingene. Ja, sys.argv
må slå opp to ting; det må slå opp sys
i ditt globale navneområde (finner modulen), og slå opp attributtet argv
. Og ja, ved å bruke from sys import argv
kan du hoppe over attributtoppslaget, siden du allerede har en direkte referanse til attributtet. Men import
utsagnet må fremdeles gjøre det arbeidet, det ser opp på samme attributt når du importerer, og du trenger bare å bruke argv
en gang . Hvis du måtte bruke argv
tusenvis av ganger i en løkke, kan det kanskje gjøre en forskjell, men i dette spesifikke tilfellet gjør det virkelig ikke .
Valget mellom den ene eller den andre da, bør være basert på kodestil i stedet.
I en stor modul , Jeg vil absolutt bruke import sys
; kodedokumentasjon betyr noe, og bruk av sys.argv
et eller annet sted i en stor modul gjør det mye klarere hva du refererer til enn bare argv
noensinne ville gjort.
Hvis det eneste stedet du bruker argv
er i en "__main__"
-blokk for å ringe en main()
-funksjon, bruk for all del from sys import argv
hvis du føler deg lykkeligere med det:
if __name__ == "__main__": from sys import argv main(argv)
I «d bruker fortsatt import sys
der selv. Alt er likt (og de er, nøyaktig, når det gjelder ytelse og antall tegn som brukes til å skrive det) , det er bare lettere for øyet.
Hvis du importerer noe annet helt, så kan ytelse spille inn. Men bare hvis du bruker et bestemt navn i en modul mange ganger , for eksempel i en kritisk sløyfe. Men å lage et lokalt navn (i en funksjon) vil fortsatt være raskere:
import somemodule def somefunction(): localname = somemodule.somefunctionorother while test: # huge, critical loop foo = localname(bar)
Kommentarer
- Det er også situasjonen der du har en pakke med underpakker eller moduler som avslører et attributt for en av disse underpakningene / modulene i toppnivåpakken. Ved å bruke
from...import
kan du gjørepackage.attribute
i stedet forpackage.subpackage_or_module.attribute
, noe som kan være nyttig hvis du ha logiske eller konseptuelle grupperinger i pakken, men vil gjøre ting litt mer praktisk for brukere av pakken din. (numpy
gjør noe slikt, tror jeg.) - I django har du mange flekker der ting som
from django.core.management.base import BaseCommand
er bedre, og alt annet (spesieltimport django
) vil føre til uleselig kode. Så mens jeg liker dette svaret, tror jeg det er noen biblioteker (og spesielt noen rammer) der konvensjonen skal bryte den nakne importen.Bruk som alltid din skjønn om hva som er best i en gitt situasjon. Men feil på siden av eksplisitt (med andre ord er jeg enig for det meste). - @JAB: du kan fortsatt bruke
import ... as
for å finne pakken til et annet navn:import package.subpackage_or_module as shortname
.from parent import sub
gjør i det vesentlige det samme. -
so wether you use import sys or from sys import argv makes no odds
dette ser ut til å ikke være tilfelle med IDLE. bare import av modulen importerer ikke funksjonene, og jeg kan bare kalle den i IDLE-skall ved å < modul >. < -funksjon > navn - @Suncatcher: les svaret mitt i sin helhet. Setningen du siterer snakker om hvor mye som importeres, ikke hvilket navn som er bundet. At ‘ er dekket andre steder i svaret.
Svar
Det er to grunner til å bruke import module
i stedet for from module import function
.
Først er navnområdet. Å importere en funksjon til det globale navneområdet risikerer navnekollisjoner.
Andre er ikke det som er relevant for standardmoduler, men viktig for deg som eier moduler, spesielt under utvikling. Det er alternativet å reload()
en modul. Tenk på dette:
from module import func ... reload(module) # func still points to the old code
På den annen side
import module ... reload(module) # module.func points to the new code
Når det gjelder hastighet .. .
vi importerer bare funksjonen som trengs i stedet for å importere hele modulen (som inneholder flere ubrukelige funksjoner som python vil kaste bort tid på å importere dem)
Enten du importerer en modul eller importerer en funksjon fra en modul, vil Python analysere hele modulen. Uansett importeres modulen. «Importere en funksjon» er ikke annet enn å binde funksjonen til et navn. Faktisk er import module
mindre arbeid for tolk enn from module import func
.
Kommentarer
- reload () var en innebygd i Python 2; det er ikke lenger tilfelle for Python 3.
- Jeg trodde det også var implikasjoner å gjøre med sirkulære importavhengigheter?
Svar
Jeg bruker from import
s når det forbedrer lesbarheten. For eksempel foretrekker jeg (semikolon er bare for å spare plass her):
from collections import defaultdict from foomodule import FooBar, FooBaz from twisted.internet.protocol import Factory defaultdict(); FooBar(); FooBaz(); Factory()
i stedet for:
import collections import foomodule import twisted.internet.protocol collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz() twisted.internet.protocol.Factory()
Sistnevnte er vanskeligere å lese (og skrive) for meg fordi den inneholder så mye overflødig informasjon. Det er også nyttig å vite på forhånd hvilke deler av en modul jeg bruker.
Jeg foretrekker vanlige import
s hvis jeg bruker mye med korte navn fra en modul:
import sys sys.argv; sys.stderr; sys.exit()
Eller hvis et navn er så generisk at det ikke gir mening utenfor navnområdet:
import json json.loads(foo) from json import loads loads(foo) # potentially confusing
Kommentarer
- Dette er favorittsvaret mitt. ‘ Eksplisitt er bedre enn implisitt ‘ noen ganger i konflikt med lesbarhet, enkelhet og TØRR. Spesielt når du bruker et rammeverk som Django.
Svar
Etter min mening bruker jeg vanlig import
forbedrer lesbarheten. Når jeg vurderer Python-kode, liker jeg å se hvor den gitte funksjonen eller klassen kommer fra akkurat der den brukes. Det sparer meg for å bla til toppen av modulen for å få den informasjonen.
Når det gjelder de lange modulnavnene, bruker jeg bare as
søkeordet og gir dem korte aliaser:
import collections as col import foomodule as foo import twisted.internet.protocol as twip my_dict = col.defaultdict() foo.FooBar() twip_fac = twip.Factory()
Som unntak bruker jeg alltid from module import something
-notasjonen når jeg håndterer __future__
-modul. Du kan bare ikke gjøre det på en annen måte når du vil at alle strengene skal være unicode som standard i Python 2, f.eks.
from __future__ import unicode_literals from __future__ import print_function
Kommentarer
- Amen! » importer som » er en vinnerkombinasjon 🙂
Svar
Selv om import sys
og from sys import agrv
begge importerer hele sys
-modulen, sistnevnte bruker navnebinding slik at bare argv
-modulen er tilgjengelig for resten av koden.
For noen mennesker vil dette være den foretrukne stilen, siden den bare gjør tilgjengelig den funksjonen du eksplisitt har oppgitt.
Det introduserer imidlertid potensielle navnekonflikter. Hva om du hadde en annen modul kalt argv
? Merk at du også eksplisitt kan importere funksjonen og gi nytt navn med from sys import argv as sys_argv
, en konvensjon som oppfyller den eksplisitte importen og som mindre sannsynlig gir navnet plass kollisjoner.
Kommentarer
- Så hvordan er
if sys_argv:
noe bedre ennif sys.argv:
? Jeg vet hva den andre uttalelsen betyr, jeg aner ikke hva den første formen betyr uten å gå tilbake til den bisarre importen.
Svar
Jeg spurte nylig dette spørsmålet til meg selv. Jeg tidsbestemte de forskjellige metodene.
forespørsler bibliotek
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
vakker soppebibliotek
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-bibliotek
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-bibliotek
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
Det ser ut til meg at det er en liten forskjell i ytelse.
Kommentarer
- Du legger til i et attributtoppslag. For å sammenligne
import module
medfrom module import name
riktig, legg til navnetoppslaget tilimport module
sak. F.eks. legg til linjensys.argv
tilar
-testen osv. Det vil fortsatt være en forskjell, fordi arbeidet som er utført er litt forskjellig, ettersom forskjellig bytekode genereres og forskjellige kodestier blir utført. - Merk at jeg adresserer den forskjellen direkte i svaret mitt; det vil være en forskjell mellom å bruke
import sys
og deretter brukesys.argv
tusenvis av ganger i en løkke vs.from sys import argv
bruk deretter bareargv
. Men du don ‘ t. For ting du bare gjør en gang på det globale nivået i modulen din, bør du virkelig optimalisere for lesbarhet, ikke mikroskopiske forskjeller i tidsinnstillinger. - Ahhhh! Og jeg trodde jeg var på vei til noe! 🙂 Jeg skummet bare svaret ditt. Det ser ut til at jeg hoppet pistolen på den. Føles bra å bli ydmyket.
Svar
Ser på publiserte kodefragmenter, importerer hele moduler og refererer til module.function
er ganske mye standarden, i det minste for standardmoduler. Det ene unntaket ser ut til å være datetime
from datetime import datetime, timedelta
slik at du kan si datetime.now()
i stedet for datetime.datetime.now()
.
Hvis du er bekymret for ytelse, kan du alltid si (for eksempel)
argv = sys.argv
og gjør deretter din ytelseskritiske kode siden moduloppslaget allerede er gjort. Men selv om dette vil fungere med funksjoner / metoder, vil de fleste IDEer bli forvirret og vil ikke (for eksempel) vise en kildekobling / signatur for funksjonen når den er tildelt en variabel.
Svar
Jeg vil bare legge til at hvis du gjør noe sånt som
from math import sin
(eller et hvilket som helst annet innebygd bibliotek som sys
eller posix
), så vil sin
inkluderes i dokumentasjonen for modulen din (dvs. når du gjør >>> help(mymodule)
eller $ pydoc3 mymodule
. For å unngå dette, importer ved å bruke:
import math from math import sin as _sin
PS: et innebygd bibliotek er et som er samlet fra C-kode og følger med Python. argparse
, os
og io
er ikke innebygde pakker
from … import …
syntaks i Python