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 wykonanie package.attribute zamiast package.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ę, że numpy 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łaszcza import 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 z from module import name, dodaj to wyszukiwanie nazwy do import module. Na przykład. dodaj wiersz sys.argv do testu ar 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żywaniem sys.argv tysięcy razy w pętli a from sys import argv, a następnie po prostu argv. 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

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *