Zawsze używałem tej metody:
from sys import argv
i użyj argv
z argv . Ale istnieje konwencja używania tego:
import sys
i używania argv przez sys.argv
Druga metoda sprawia, że kod zostaje samodokumentowany i (naprawdę) się go trzymam. Ale powodem, dla którego wolę pierwszą metodę, jest to, że jest szybka, ponieważ importujemy tylko potrzebną funkcję, a nie cały moduł (który zawiera więcej bezużytecznych funkcji, które python marnuje czas na ich importowanie). Zauważ, że potrzebuję tylko argv, a wszystkie inne funkcje z sys są dla mnie bezużyteczne.
Więc moje pytania są. Czy pierwsza metoda naprawdę przyspiesza skrypt? Która metoda jest najbardziej preferowana? Dlaczego?
Komentarze
Odpowiedź
Importowanie modułu nie marnuje niczego ; moduł jest zawsze w pełni zaimportowane (do mapowania sys.modules
), więc czy używasz import sys
czy from sys import argv
nie ma szans.
Jedyną różnicą między tymi dwoma instrukcjami jest to, jaka nazwa jest powiązana; import sys
wiąże nazwę sys
do modułu (więc sys
-> sys.modules["sys"]
), podczas gdy from sys import argv
wiąże inna nazwa, argv
, wskazująca bezpośrednio na atrybut zawarty w module (więc argv
-> sys.modules["sys"].argv
). Reszta Moduł sys
nadal istnieje, niezależnie od tego, czy używasz czegoś innego z modułu, czy nie.
Nie ma również różnicy w wydajności między tymi dwoma podejściami. Tak, sys.argv
musi sprawdzić dwie rzeczy; musi znaleźć sys
w twojej globalnej przestrzeni nazw (znajduje moduł), a następnie wyszukać atrybut argv
. I tak, używając from sys import argv
, możesz pominąć wyszukiwanie atrybutu, ponieważ masz już bezpośrednie odniesienie do atrybutu. Ale instrukcja import
nadal musi wykonać tę pracę, wyszukuje ten sam atrybut podczas importowania, a Ty „zawsze będziesz musiał używać tylko argv
raz . Gdybyś musiał użyć argv
tysiące razy w pętli, może to coś zmienić, ale w tym konkretnym przypadku tak naprawdę nie .
W takim przypadku wybór między jednym a drugim powinien opierać się na stylu kodowania .
W dużym module , Na pewno użyję import sys
; dokumentacja kodu ma znaczenie, a użycie sys.argv
gdzieś w dużym module sprawia, że jest o wiele jaśniejsze, do czego się odnosisz, niż by to było kiedykolwiek możliwe.
Jeśli jedyne miejsce, którego używasz argv
, znajduje się w bloku "__main__"
, aby zadzwonić do main()
, na wszelki wypadek użyj from sys import argv
, jeśli czujesz się szczęśliwszy:
if __name__ == "__main__": from sys import argv main(argv)
I „d nadal używam import sys
tam osobiście. Wszystkie rzeczy są równe (i są dokładnie pod względem wydajności i liczby znaków użytych do napisania tego) , to jest dla mnie po prostu łatwiejsze dla oka.
Jeśli importujesz coś innego , być może w grę wchodzi wydajność. Ale tylko wtedy, gdy używasz określonej nazwy w moduł wielokrotnie , na przykład w pętli krytycznej. Ale wtedy tworzenie nazwy lokalnej (w funkcji) będzie jeszcze szybsze:
import somemodule def somefunction(): localname = somemodule.somefunctionorother while test: # huge, critical loop foo = localname(bar)
Komentarze
- Istnieje również sytuacja, w której masz pakiet z podpakietami lub modułami, które ujawniają atrybut jednego z tych podpakietów / modułów w pakiecie najwyższego poziomu. Korzystanie z
from...import
umożliwia wykonaniepackage.attribute
zamiastpackage.subpackage_or_module.attribute
, co może być przydatne, jeśli mają logiczne lub koncepcyjne grupy w pakiecie, ale chcą uczynić to nieco wygodniejszym dla użytkowników pakietu. (Myślę, żenumpy
robi coś takiego). - W django masz mnóstwo miejsc, w których takie rzeczy jak
from django.core.management.base import BaseCommand
są lepsze, a wszystko inne (zwłaszczaimport django
) doprowadziłoby do nieczytelnego kodu. Tak więc, chociaż podoba mi się ta odpowiedź, myślę, że są biblioteki (a zwłaszcza niektóre frameworki), w których konwencja jest naruszeniem samego importu.Jak zawsze, oceniaj, co jest najlepsze w danej sytuacji. Ale popełniaj błędy po stronie wyraźnych (innymi słowy, w większości się zgadzam). - @JAB: nadal możesz użyć
import ... as
, aby znaleźć pakiet do inna nazwa:import package.subpackage_or_module as shortname
.from parent import sub
zasadniczo robi to samo. -
so wether you use import sys or from sys import argv makes no odds
wydaje się, że tak nie jest w przypadku IDLE. samo zaimportowanie modułu nie powoduje zaimportowania jego funkcji i mogę go wywołać w powłoce IDLE tylko przez < moduł >. < funkcja > nazwa - @Suncatcher: przeczytaj moją odpowiedź w całości. Cytowane zdanie mówi o tym, ile jest importowane, a nie o tym, jakie imię jest związane. To ' zostało omówione w innym miejscu odpowiedzi.
Odpowiedź
Istnieją dwa powody, dla których warto używać import module
zamiast from module import function
.
Pierwsza to przestrzeń nazw. Importowanie funkcji do globalnej przestrzeni nazw stwarza ryzyko kolizji nazw.
Po drugie, nie jest to tak istotne dla standardowych modułów, ale istotne dla posiadanych modułów, zwłaszcza podczas programowania. Jest to opcja reload()
moduł. Rozważ to:
from module import func ... reload(module) # func still points to the old code
Z drugiej strony
import module ... reload(module) # module.func points to the new code
Jeśli chodzi o szybkość … .
importujemy tylko potrzebną funkcję, zamiast importować cały moduł (który zawiera więcej bezużytecznych funkcji, które python marnuje czas na ich importowanie)
Niezależnie od tego, czy importujesz moduł, czy importujesz funkcję z modułu, Python przeanalizuje cały moduł. W każdym przypadku moduł jest importowany. „Importowanie funkcji” to nic innego jak powiązanie funkcji z nazwą. W rzeczywistości import module
wymaga mniej pracy dla tłumacza niż from module import func
.
Komentarze
- reload () było wbudowane w Pythonie 2; tak już nie jest w przypadku Pythona 3.
- Myślałem, że są też konsekwencje związane z cyklicznymi zależnościami importu?
Odpowiedź
Używam from import
s zawsze, gdy poprawia to czytelność. Na przykład wolę (średniki służą tylko do zaoszczędzenia miejsca):
from collections import defaultdict from foomodule import FooBar, FooBaz from twisted.internet.protocol import Factory defaultdict(); FooBar(); FooBaz(); Factory()
zamiast:
import collections import foomodule import twisted.internet.protocol collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz() twisted.internet.protocol.Factory()
Ten ostatni jest dla mnie trudniejszy do odczytania (i napisania), ponieważ zawiera tak dużo zbędnych informacji. Warto również wcześniej wiedzieć, jakich części modułu używam.
Wolę zwykłe import
, jeśli używam dużo krótkich nazw z modułu:
import sys sys.argv; sys.stderr; sys.exit()
Lub jeśli nazwa jest tak ogólna, że nie ma sensu poza swoją przestrzenią nazw:
import json json.loads(foo) from json import loads loads(foo) # potentially confusing
Komentarze
- To moja ulubiona odpowiedź. ' Wulgarne jest lepsze niż niejawne ' czasami koliduje z czytelnością, prostotą i DRY. Zwłaszcza jeśli używasz frameworka takiego jak Django.
Odpowiedź
Moim zdaniem używając zwykłego import
poprawia czytelność. Podczas przeglądania kodu Pythona lubię widzieć, skąd dana funkcja lub klasa pochodzi z miejsca, w którym jest używana. Oszczędza mi to przewijania do góry modułu w celu uzyskania tych informacji.
Jeśli chodzi o długie nazwy modułów, używam po prostu słowa kluczowego as
i nadaję im krótkie aliasy:
import collections as col import foomodule as foo import twisted.internet.protocol as twip my_dict = col.defaultdict() foo.FooBar() twip_fac = twip.Factory()
Jako wyjątek zawsze używam notacji from module import something
, gdy mam do czynienia z __future__
. Po prostu nie możesz tego zrobić inaczej, jeśli chcesz, aby wszystkie ciągi znaków były domyślnie unicode w Pythonie 2, np.
from __future__ import unicode_literals from __future__ import print_function
Komentarze
- Amen! ” import as ” to zwycięska kombinacja 🙂
Odpowiedź
Chociaż import sys
i from sys import agrv
oba importują cały moduł sys
, ten ostatni używa wiązania nazwy, więc tylko moduł argv
jest dostępny dla reszty kodu.
Dla niektórych ludzi byłby to preferowany styl, ponieważ udostępnia on tylko funkcję, którą wyraźnie podałeś.
Wprowadza jednak potencjalne konflikty nazw. Co by było, gdybyś miał inny moduł o nazwie argv
? Zwróć uwagę, że możesz również jawnie zaimportować funkcję i zmienić jej nazwę za pomocą from sys import argv as sys_argv
, konwencji, która jest zgodna z jawnym importem i jest mniej prawdopodobne, że zapewni przestrzeń nazw kolizje.
Komentarze
- W jaki sposób
if sys_argv:
jest lepszy niżif sys.argv:
? Wiem, co oznacza drugie stwierdzenie, nie mam pojęcia, co oznacza pierwsza forma bez cofania się do dziwacznego importu.
Odpowiedź
Niedawno zadałem sobie to pytanie. Zmierzyłem czas dla różnych metod.
żąda biblioteki
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
biblioteka beautifulsoup
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
biblioteka json
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
biblioteka sys
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
Wydaje się, że ja, że istnieje niewielka różnica w wydajności.
Komentarze
- Dodajesz wyszukiwanie atrybutu. Aby poprawnie porównać
import module
zfrom module import name
, dodaj to wyszukiwanie nazwy doimport module
. Na przykład. dodaj wierszsys.argv
do testuar
itp. Nadal będzie różnica, ponieważ wykonana praca jest nieznacznie różne, ponieważ generowany jest inny kod bajtowy i wykonywane są różne ścieżki kodowe. - Zauważ, że bezpośrednio odnoszę się do tej różnicy w mojej odpowiedzi; będzie różnica między używaniem
import sys
a używaniemsys.argv
tysięcy razy w pętli afrom sys import argv
, a następnie po prostuargv
. Ale nie ' t. W przypadku rzeczy, które robisz raz na globalnym poziomie swojego modułu, naprawdę powinieneś zoptymalizować pod kątem czytelności, a nie mikroskopijnych różnic w czasie. - Ahhhh! I myślałem, że coś się dzieje! 🙂 Tylko przejrzałem twoją odpowiedź. Wygląda na to, że skoczyłem na niego. Dobrze jest być pokornym.
Odpowiedź
Przeglądanie opublikowanych fragmentów kodu, importowanie całych modułów i odwoływanie się do module.function
jest prawie standardem, przynajmniej dla standardowych modułów. Jedynym wyjątkiem wydaje się być datetime
from datetime import datetime, timedelta
, więc możesz powiedzieć datetime.now()
zamiast datetime.datetime.now()
.
Jeśli martwisz się o wydajność, zawsze możesz powiedzieć (na przykład)
argv = sys.argv
, a następnie wykonaj kod krytyczny dla wydajności, ponieważ wyszukiwanie modułu jest już wykonane. Jednakże, chociaż zadziała to z funkcjami / metodami, większość IDE będzie zdezorientowanych i nie będzie (na przykład) wyświetlać linku / sygnatury źródłowej dla funkcji, gdy jest ona przypisana do zmiennej.
Odpowiedź
Chcę tylko dodać, że jeśli zrobisz coś takiego jak
from math import sin
(lub dowolną inną wbudowaną biblioteką, taką jak sys
lub posix
), a następnie sin
być uwzględnione w dokumentacji modułu (np. gdy wykonujesz >>> help(mymodule)
lub $ pydoc3 mymodule
). Aby tego uniknąć, importuj używając:
import math from math import sin as _sin
PS: wbudowana biblioteka to taka, która jest kompilowana z kodu C i dołączona do Pythona. argparse
, os
i io
nie są pakietami wbudowanymi
from … import …
składni w Pythonie