Jag har alltid använt den här metoden:
from sys import argv
och använd argv
med bara argv . Men det finns en konvention att använda detta:
import sys
och använda argv av sys.argv
Den andra metoden gör koden självdokumenterad och jag (verkligen) följer den. Men anledningen till att jag föredrar den första metoden är att det är snabbt eftersom vi bara importerar den funktion som behövs snarare än att importera hela modulen (som innehåller mer värdelösa funktioner som python slösar bort tid på att importera dem). Observera att jag bara behöver argv och alla andra funktioner från sys är värdelösa för mig.
Så mina frågor är. Gör den första metoden verkligen manuset snabbt? Vilken metod föredras mest? Varför?
Kommentarer
Svar
Import av modulen slösar inte någonting ; modulen är alltid helt importerad (till sys.modules
-mappningen), så oavsett om du använder import sys
eller from sys import argv
gör inga odds.
Den enda skillnaden mellan de två påståendena är vad namnet är bundet. import sys
binder namnet sys
till modulen (så sys
-> sys.modules["sys"]
), medan from sys import argv
binder ett annat namn, argv
, som pekar rakt mot attributet som finns inne i modulen (så argv
-> sys.modules["sys"].argv
). Resten av den e sys
-modulen finns kvar, oavsett om du använder något annat från modulen eller inte.
Det finns inte heller någon skillnad i prestanda mellan de två metoderna. Ja, sys.argv
måste slå upp två saker; det måste slå upp sys
i ditt globala namnområde (hittar modulen) och leta sedan upp attributet argv
. Och ja, genom att använda from sys import argv
kan du hoppa över attributsökning, eftersom du redan har en direkt hänvisning till attributet. Men uttalandet import
måste fortfarande göra det, det slår upp samma attribut när du importerar och du behöver bara använda argv
en gång . Om du skulle behöva använda argv
tusentals gånger i en slinga kan det kanske göra skillnad, men i det här specifika fallet gör det verkligen inte .
Valet mellan den ena eller den andra bör i stället baseras på kodningsstil .
I en stor modul , Jag skulle verkligen använda import sys
; koddokumentation spelar roll, och att använda sys.argv
någonstans i en stor modul gör det mycket tydligare vad du hänvisar till än bara argv
någonsin skulle göra.
Om det enda stället du använder argv
är i ett "__main__"
-block för att ringa ett main()
-funktion, använd i alla fall from sys import argv
om du känner dig lyckligare över det:
if __name__ == "__main__": from sys import argv main(argv)
I ”d använder fortfarande import sys
där själv. Allting är lika (och de är exakt, när det gäller prestanda och antalet tecken som används för att skriva det) , det är bara lättare för ögat för mig.
Om du importerar något annat helt och hållet, kanske prestanda spelar in. Men bara om du använder ett specifikt namn i en modul många gånger , till exempel i en kritisk slinga. Men att skapa ett lokalt namn (inom en funktion) kommer fortfarande att vara snabbare:
import somemodule def somefunction(): localname = somemodule.somefunctionorother while test: # huge, critical loop foo = localname(bar)
Kommentarer
- Det finns också en situation där du har ett paket med underpaket eller moduler som exponerar ett attribut för ett av dessa delpaket / moduler i toppnivåpaketet. Med hjälp av
from...import
kan du görapackage.attribute
istället förpackage.subpackage_or_module.attribute
, vilket kan vara användbart om du ha logiska eller konceptuella grupperingar inom paketet men vill göra sakerna lite bekvämare för användare av ditt paket. (numpy
gör något sådant tror jag.) - I django har du massor av platser där saker som
from django.core.management.base import BaseCommand
är bättre, och allt annat (särskiltimport django
) skulle leda till oläslig kod. Så även om jag gillar det här svaret tror jag att det finns några bibliotek (och särskilt vissa ramar) där konventionen är att bryta mot den rena importen.Använd som alltid ditt omdöme om vad som är bäst i en given situation. Men fel på sidan av uttryckligt (med andra ord håller jag för det mesta). - @JAB: du kan fortfarande använda
import ... as
för att hitta paketet till ett annat namn:import package.subpackage_or_module as shortname
.from parent import sub
gör i princip samma sak. -
so wether you use import sys or from sys import argv makes no odds
detta verkar inte vara fallet med IDLE. bara import av modulen importerar inte dess funktioner och jag kan bara kalla den i IDLE-skal med < modul >. < -funktion > namn - @Suncatcher: läs mitt svar fullständigt. Den mening du citerar talar om hur mycket som importeras, inte vilket namn som är bundet. Att ’ täcks någon annanstans i svaret.
Svar
Det finns två skäl för att använda import module
istället för from module import function
.
Först är namnområdet. Att importera en funktion till det globala namnområdet riskerar namnkollisioner.
För det andra är det inte relevant för standardmoduler, men viktigt för dina egna moduler, särskilt under utvecklingen. Det är alternativet att reload()
en modul. Tänk på detta:
from module import func ... reload(module) # func still points to the old code
Å andra sidan
import module ... reload(module) # module.func points to the new code
När det gäller hastighet .. .
vi importerar bara den funktion som behövs snarare än att importera hela modulen (som innehåller fler värdelösa funktioner som python slösar bort tid på att importera dem)
Oavsett om du importerar en modul eller importerar en funktion från en modul analyserar Python hela modulen. Hursomhelst modulen importeras. ”Importera en funktion” är inget annat än att binda funktionen till ett namn. Faktum är att import module
är mindre arbete för tolk än from module import func
.
Kommentarer
- reload () var ett inbyggt i Python 2; är det inte längre fallet för Python 3.
- Jag trodde att det också fanns konsekvenser för cirkulära importberoenden?
Svar
Jag använder from import
s när det förbättrar läsbarheten. Till exempel föredrar jag (semikolon är bara för att spara utrymme här):
from collections import defaultdict from foomodule import FooBar, FooBaz from twisted.internet.protocol import Factory defaultdict(); FooBar(); FooBaz(); Factory()
istället för:
import collections import foomodule import twisted.internet.protocol collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz() twisted.internet.protocol.Factory()
Det senare är svårare att läsa (och skriva) för mig eftersom det innehåller så mycket överflödig information. Det är också bra att veta i förväg vilka delar av en modul jag använder.
Jag föredrar vanliga import
om jag använder partier korta namn från en modul:
import sys sys.argv; sys.stderr; sys.exit()
Eller om ett namn är så generiskt att det inte är meningsfullt utanför namnområdet:
import json json.loads(foo) from json import loads loads(foo) # potentially confusing
Kommentarer
- Detta är mitt favoritsvar. ’ Explicit är bättre än implicit ’ ibland strider mot läsbarhet, enkelhet och TORR. Speciellt när man använder en ram som Django.
Svar
Enligt min mening använder jag vanlig import
förbättrar läsbarheten. När jag granskar Python-koden vill jag se var den givna funktionen eller klassen kommer från precis där den används. Det sparar mig från att bläddra till toppen av modulen för att få den informationen.
När det gäller de långa modulnamnen använder jag bara nyckelordet as
och ger dem korta alias:
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 ett undantag använder jag alltid from module import something
-notationen när jag hanterar __future__
-modul. Du kan bara inte göra det på ett annat sätt när du vill att alla strängar ska vara unicode som standard i Python 2, t.ex.
from __future__ import unicode_literals from __future__ import print_function
Kommentarer
- Amen! ” importera som ” är en vinnande kombination 🙂
Svar
Även om import sys
och from sys import agrv
båda importerar hela sys
-modulen, den senare använder namnbindning så att endast argv
-modulen är tillgänglig för resten av koden.
För vissa människor skulle detta vara den önskade stilen eftersom den bara gör den funktion som du uttryckligen angav tillgänglig.
Det introducerar emellertid potentiella namnkonflikter. Vad händer om du hade en annan modul som heter argv
? Observera att du också kan uttryckligen importera funktionen och byta namn med from sys import argv as sys_argv
, en konvention som uppfyller den uttryckliga importen och är mindre benägna att ge namn kollisioner.
Kommentarer
- Så hur är
if sys_argv:
bättre änif sys.argv:
? Jag vet vad det andra uttalandet betyder, jag har ingen aning om vad den första formen betyder utan att gå tillbaka till den bisarra importen.
Svar
Jag ställde nyligen den här frågan till mig själv. Jag har tidsinställt de olika metoderna.
begär 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
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
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 verkar mig att det finns en liten skillnad i prestanda.
Kommentarer
- Du lägger till i en attributsökning. För att jämföra
import module
medfrom module import name
korrekt, lägg till det namnuppslaget tillimport module
fall. T.ex. lägg till radensys.argv
tillar
-testet etc. Det kommer fortfarande att finnas en skillnad, eftersom det utförda arbetet är något annorlunda, eftersom olika bytecode genereras och olika kodvägar körs. - Observera att jag direkt adresserar den skillnaden i mitt svar; det kommer att finnas en skillnad mellan att använda
import sys
och sedan användasys.argv
tusentals gånger i en slinga kontrafrom sys import argv
använder sedan baraargv
. Men du behöver inte ’ t. För saker du bara gör en gång på din globala nivå bör du verkligen optimera för läsbarhet, inte mikroskopiska skillnader i tidsinställningar. - Ahhhh! Och jag trodde att jag var ute efter något! 🙂 Jag skumrade bara ditt svar. Det verkar som att jag hoppade på pistolen på den. Känns bra att vara ödmjuk.
Svar
Tittar på publicerade kodfragment, importerar hela moduler och hänvisar till module.function
är ganska mycket standard, åtminstone för standardmoduler. Det enda undantaget verkar vara datetime
from datetime import datetime, timedelta
så att du kan säga datetime.now()
snarare än datetime.datetime.now()
.
Om du är orolig för prestanda kan du alltid säga (till exempel)
argv = sys.argv
och gör sedan din prestandakritiska kod eftersom moduluppsökningen redan är klar. Men även om detta kommer att fungera med funktioner / metoder kommer de flesta IDE: er att bli förvirrade och kommer inte (t) visa en källlänk / signatur för funktionen när den tilldelas en variabel.
Svar
Jag vill bara lägga till att om du gör något som
from math import sin
(eller något annat inbyggt bibliotek som sys
eller posix
), så kommer sin
inkluderas i dokumentationen för din modul (dvs. när du gör >>> help(mymodule)
eller $ pydoc3 mymodule
. För att undvika detta, importera med:
import math from math import sin as _sin
PS: ett inbyggt bibliotek är ett som sammanställs från C-kod och ingår i Python. argparse
, os
och io
är inte inbyggda paket
from … import …
syntax i Python