Jeg har altid brugt denne metode:

from sys import argv 

og brug argv med bare argv . Men der er en konvention at bruge dette:

import sys 

og bruge argv ved sys.argv

Den anden metode gør koden selvdokumenteret, og jeg (virkelig) overholder den. Men grunden til, at jeg foretrækker den første metode, er, at den er hurtig, fordi vi kun importerer den nødvendige funktion i stedet for at importere hele modulet (som indeholder flere ubrugelige funktioner, som python spilder tid på at importere dem). Bemærk, at jeg bare har brug for argv, og alle andre funktioner fra sys er ubrugelige for mig.

Så mine spørgsmål er. Gør den første metode virkelig scriptet hurtigt? Hvilken metode foretrækkes mest? Hvorfor?

Kommentarer

Svar

Import af modulet spilder ikke noget ; modulet er altid fuldt ud importeret (til sys.modules kortlægning), så uanset om du bruger import sys eller from sys import argv giver ingen odds.

Den eneste forskel mellem de to udsagn er, hvad navnet er bundet; import sys binder navnet sys til modulet (så sys -> sys.modules["sys"]), mens from sys import argv binder et andet navn, argv, der peger lige på attributten inde i modulet (så argv -> sys.modules["sys"].argv). Resten af th e sys -modulet er der stadig, uanset om du bruger noget andet fra modulet eller ej.

Der er heller ingen forskel i ydelse mellem de to tilgange. Ja, sys.argv skal slå to ting op; det skal slå op sys i dit globale navneområde (finder modulet) og derefter slå attributten argv op. Og ja, ved at bruge from sys import argv kan du springe over attributopslaget, da du allerede har en direkte henvisning til attributten. Men import udsagnet skal stadig udføre det arbejde, det ser op på den samme attribut, når du importerer, og du behøver kun nogensinde at bruge argv en gang . Hvis du skulle bruge argv tusinder af gange i en løkke, kunne det måske gøre en forskel, men i dette specifikke tilfælde gør det virkelig ikke .

Valget mellem den ene eller den anden skal derefter være baseret på kodningstil i stedet.

I et stort modul , Jeg ville bestemt bruge import sys; kodedokumentation betyder noget, og brug af sys.argv et eller andet sted i et stort modul gør det meget tydeligere, hvad du henviser til end bare argv nogensinde ville gøre.

Hvis det eneste sted, du bruger argv, er i en "__main__" -blok for at kalde en main() -funktion, brug på alle måder from sys import argv hvis du føler dig lykkeligere over det:

if __name__ == "__main__": from sys import argv main(argv) 

I “d bruger stadig import sys der selv. Alt lige er (og de er nøjagtigt med hensyn til ydeevne og antallet af tegn, der bruges til at skrive det) , det er bare lettere for øjet for mig.

Hvis du importerer noget andet helt, så kommer ydeevne måske til at spille. Men kun hvis du bruger et specifikt navn i en modul mange gange , f.eks. i en kritisk sløjfe. Men så vil det stadig være hurtigere at oprette et lokalt navn (inden for en funktion):

 import somemodule def somefunction(): localname = somemodule.somefunctionorother while test: # huge, critical loop foo = localname(bar) 

Kommentarer

  • Der er også den situation, hvor du har en pakke med underpakker eller moduler, der afslører en attribut for en af disse underpakker / moduler i topniveaupakken. Brug af from...import giver dig mulighed for at gøre package.attribute i stedet for package.subpackage_or_module.attribute, hvilket kan være nyttigt, hvis du har logiske eller konceptuelle grupperinger inden for pakken, men ønsker at gøre tingene lidt mere bekvemme for brugere af din pakke. (numpy gør sådan noget, tror jeg.)
  • I django har du masser af pletter, hvor ting som from django.core.management.base import BaseCommand er bedre, og alt andet (især import django) vil føre til uleselig kode. Så mens jeg kan lide dette svar, tror jeg, at der er nogle biblioteker (og især nogle rammer), hvor konventionen skal krænke den nøgne import.Brug som altid din vurdering af, hvad der er bedst i en given situation. Men fejler ved eksplicit (med andre ord er jeg for det meste enig).
  • @JAB: du kan stadig bruge import ... as til at finde pakken til et andet navn: import package.subpackage_or_module as shortname. from parent import sub gør i det væsentlige det samme.
  • so wether you use import sys or from sys import argv makes no odds dette synes ikke at være tilfældet med IDLE. bare import af modulet importerer ikke dets funktioner, og jeg kan kun kalde det i IDLE-shell ved at < modul >. < funktion > navn
  • @Suncatcher: læs mit svar fuldt ud. Den sætning, du citerer, taler om, hvor meget der importeres, ikke hvilket navn der er bundet. At ‘ er dækket andetsteds i svaret.

Svar

Der er to grunde til at bruge import module snarere end from module import function.

Først er navneområdet. Import af en funktion til det globale navneområde risikerer navnekollisioner.

Andet er ikke det, der er relevant for standardmoduler, men vigtigt for dine egne moduler, især under udvikling. Det er muligheden for at reload() et modul. Overvej dette:

from module import func ... reload(module) # func still points to the old code 

På den anden side

import module ... reload(module) # module.func points to the new code 

Hvad angår hastighed .. .

vi importerer kun den nødvendige funktion i stedet for at importere hele modulet (som indeholder flere ubrugelige funktioner, som python spilder tid på at importere dem)

Uanset om du importerer et modul eller importerer en funktion fra et modul, vil Python analysere hele modulet. Uanset hvad importeres modulet. “Import af en funktion” er intet andet end at binde funktionen til et navn. Faktisk er import module mindre arbejde for tolk end from module import func.

Kommentarer

  • reload () var en indbygget i Python 2; det er ikke længere tilfældet for Python 3.
  • Jeg troede, at der også var implikationer at gøre med cirkulære importafhængigheder?

Svar

Jeg bruger from import s, når det forbedrer læsbarheden. For eksempel foretrækker jeg (semikoloner er kun at spare plads 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() 

Sidstnævnte er sværere at læse (og skrive) for mig, fordi det indeholder så meget overflødige oplysninger. Det er også nyttigt at vide på forhånd, hvilke dele af et modul jeg bruger.

Jeg foretrækker regelmæssige import s, hvis jeg bruger partier af korte navne fra et modul:

import sys sys.argv; sys.stderr; sys.exit() 

Eller hvis et navn er så generisk, at det ikke giver mening uden for dets navneområde:

import json json.loads(foo) from json import loads loads(foo) # potentially confusing 

Kommentarer

  • Dette er mit foretrukne svar. ‘ Eksplicit er bedre end implicit ‘ er undertiden i modstrid med læsbarhed, enkelhed og TØRR. Især når man bruger en ramme som Django.

Svar

Efter min mening bruger jeg almindelig import forbedrer læsbarheden. Når jeg gennemgår Python-kode, kan jeg godt lide at se, hvor den givne funktion eller klasse kommer fra lige hvor den bruges. Det sparer mig for at rulle til toppen af modulet for at få disse oplysninger.

Hvad angår de lange modulnavne bruger jeg bare nøgleordet as og giver 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 en undtagelse bruger jeg altid from module import something notationen, når jeg beskæftiger mig med __future__ modul. Du kan bare ikke gøre det på en anden måde, når du ønsker, at alle strenge 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 vindende kombination 🙂

Svar

Selvom import sys og from sys import agrv begge importerer hele sys modulet, sidstnævnte bruger navnebinding, så kun argv -modulet er tilgængeligt for resten af koden.

For nogle mennesker vil dette være den foretrukne stil, da det kun gør den funktion tilgængelig, som du udtrykkeligt har angivet.

Det introducerer dog potentielle navnekonflikter. Hvad hvis du havde et andet modul med navnet argv? Bemærk, du kan også eksplicit importere funktionen og omdøbe med from sys import argv as sys_argv, en konvention, der opfylder den eksplicitte import og mindre tilbøjelige til at give navnet plads kollisioner.

Kommentarer

  • Så hvordan er if sys_argv: bedre end if sys.argv:? Jeg ved, hvad den anden erklæring betyder, jeg aner ikke, hvad den første form betyder uden at gå tilbage til den bizarre import.

Svar

Jeg stillede for nylig dette spørgsmål til mig selv. Jeg timede de forskellige metoder.

anmodningsbibliotek

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 

smukt 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 ud til mig at der er en lille forskel i ydeevne.

Kommentarer

  • Du tilføjer i en attributopslag. For at sammenligne import module med from module import name korrekt skal du tilføje navnetopslaget til import module sag. For eksempel. tilføj linjen sys.argv til ar testen osv. Der vil stadig være en forskel, fordi det udførte arbejde er en smule forskellige, da forskellige bytecode genereres, og forskellige codepaths udføres.
  • Bemærk, at jeg direkte adresserer denne forskel i mit svar; der vil være en forskel mellem at bruge import sys derefter bruge sys.argv tusinder af tid i en løkke vs. from sys import argv brug derefter bare argv. Men du behøver ikke ‘ t. For ting, du gør en gang på globalt niveau i dit modul, skal du virkelig optimere til læsbarhed, ikke mikroskopiske forskelle i timings.
  • Ahhhh! Og jeg troede, jeg var på noget! 🙂 Jeg skumrede kun dit svar. Det ser ud til, at jeg sprang pistolen mod den. Føles godt at blive ydmyget.

Svar

Ser på offentliggjorte kodefragmenter, importerer hele moduler og henviser til module.function er stort set standarden, i det mindste for standardmoduler. Den ene undtagelse ser ud til at være datetime

from datetime import datetime, timedelta 

så du kan sige datetime.now() snarere end datetime.datetime.now().

Hvis du er bekymret for ydeevne, kan du altid sige (for eksempel)

argv = sys.argv 

og udfør derefter din ydeevnekritiske kode, da modulopslaget allerede er gjort. Men selvom dette fungerer med funktioner / metoder, vil de fleste IDEer blive forvirrede og vinde “t (for eksempel) vise et kildelink / signatur til funktionen, når den er tildelt en variabel.

Svar

Jeg vil bare tilføje, at hvis du gør noget som

from math import sin 

(eller ethvert andet indbygget bibliotek som sys eller posix), så vil sin inkluderes i dokumentationen til dit modul (dvs. når du gør >>> help(mymodule) eller $ pydoc3 mymodule. For at undgå dette skal du importere ved hjælp af:

import math from math import sin as _sin 

PS: et indbygget bibliotek er et, der er kompileret fra C-kode og inkluderet i Python. argparse, os og io er ikke indbyggede pakker

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *