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öra package.attribute istället för package.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ärskilt import 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 än if 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 med from module import name korrekt, lägg till det namnuppslaget till import module fall. T.ex. lägg till raden sys.argv till ar -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ända sys.argv tusentals gånger i en slinga kontra from sys import argv använder sedan bara argv. 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

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *