Zaleca się, aby nie używać import *
w Pythonie.
Czy ktoś może podać powód takiego stanu rzeczy, abym mógł tego uniknąć następnym razem?
python
python-import
Entuzjastyczne oprogramowanie
źródło
źródło
import *
u mnie nie działa na pierwszym miejscu w Pythonie 2 lub 3.Odpowiedzi:
Ponieważ umieszcza dużo rzeczy w twojej przestrzeni nazw (może przesłonić jakiś inny obiekt z poprzedniego importu i nie będziesz o tym wiedział).
Ponieważ nie wiesz dokładnie, co jest importowane i nie możesz łatwo znaleźć, z którego modułu dana rzecz została zaimportowana (czytelność).
Ponieważ nie możesz używać fajnych narzędzi, takich jak
pyflakes
statyczne wykrywanie błędów w kodzie.źródło
numpy.any
cieniowanie,any
kiedy to robią,from numpy import *
lub „pomocne” narzędzie robi to za nich.import *
sprawia, że kolejność tychimport
wypowiedzi znaczących ... nawet dla standardowych modułów bibliotecznych, które zazwyczaj nie dbają o celu importu . Coś tak niewinnego, jak alfabetowanieimport
wypowiedzi, może złamać twój skrypt, gdy była ofiara wojny importowej zostanie jedyną ocalałą. (Nawet jeśli twój skrypt działa teraz i nigdy się nie zmienia, może nagle zawieść jakiś czas później, jeśli zaimportowany moduł wprowadzi nową nazwę, która zastąpi tę, na której polegałeś.)Według Zen of Python :
... na pewno nie możesz się z tym kłócić?
źródło
use strict
(JavaScriptvar
). Nawiasem mówiąc , oczywiście Python nie jest bez typu (w rzeczywistości jest silnie wpisany). W każdym razie, nawet gdybyś miał rację, nadal byłoby to sprzeczne z Zen Pythona, cytowanym w tej odpowiedzi.Nie przechodzisz
**locals()
do funkcji, prawda?Ponieważ Python brakuje „zawierać” oświadczenie, a
self
parametr jest wyraźny, a zasady określania zakresu są dość proste, to zwykle bardzo łatwo wskazać palcem na zmiennej i powiedzieć, gdzie ten przedmiot pochodzi od - bez czytania innych modułów i bez jakiejkolwiek IDE (które i tak są ograniczone ze względu na introspekcję, ponieważ język jest bardzo dynamiczny).To
import *
wszystko psuje.Posiada również konkretną możliwość ukrywania błędów.
Teraz, jeśli moduł bar ma którykolwiek z atrybutów „
os
”, „mystuff
”, itp., Nadpisuje atrybuty jawnie zaimportowane i prawdopodobnie wskaże na bardzo różne rzeczy. Definiowanie__all__
w pasku jest często rozsądne - określa to, co zostanie niejawnie zaimportowane - ale nadal trudno jest prześledzić, skąd pochodzą obiekty, bez czytania i analizowania modułu paska i śledzenia jego importu. Siećimport *
to pierwsza rzecz, którą naprawiam, gdy przejmuję projekt na własność.Nie zrozum mnie źle: gdyby tego
import *
brakowało, płakałbym, żeby go mieć. Ale należy go używać ostrożnie. Dobrym przypadkiem użycia jest zapewnienie interfejsu fasady nad innym modułem. Podobnie, użycie warunkowych instrukcji importu lub importu wewnątrz przestrzeni nazw funkcji / klas wymaga pewnej dyscypliny.Myślę, że w średnich i dużych projektach lub małych z kilkoma współpracownikami, minimalna higiena jest potrzebna pod względem analizy statycznej - uruchomienie przynajmniej pyflakes lub jeszcze lepiej odpowiednio skonfigurowanego pylinta - aby złapać kilka rodzajów błędów wcześniej zdarzają się.
Oczywiście, ponieważ jest to Python - nie krępuj się łamać zasad i eksplorować - ale uważaj na projekty, które mogą wzrosnąć dziesięciokrotnie, jeśli w kodzie źródłowym brakuje dyscypliny, będzie to problem.
źródło
execfile()
. Na szczęście jest rzadko używany i zniknął w 3.x.**vars()
na dołączenie zmiennych globalnych, jeśli wywoływana funkcja znajduje się w innym pliku? : PMożna to zrobić
from ... import *
w sesji interaktywnej.źródło
doctest
sznurka? Czyimport *
w tym przypadku jest interpretowany wewnątrz „piaskownicy”? Dzięki.Dzieje się tak, ponieważ zanieczyszczasz przestrzeń nazw. Zaimportujesz wszystkie funkcje i klasy do własnej przestrzeni nazw, co może kolidować z funkcjami, które sam zdefiniujesz.
Ponadto uważam, że użycie nazwy kwalifikowanej jest bardziej zrozumiałe w przypadku zadania konserwacyjnego; w samym wierszu kodu widzisz, skąd pochodzi funkcja, dzięki czemu możesz znacznie łatwiej sprawdzić dokumenty.
W module foo:
W swoim kodzie:
źródło
http://docs.python.org/tutorial/modules.html
źródło
Powiedzmy, że masz następujący kod w module o nazwie foo:
a następnie we własnym module masz:
Masz teraz trudny do debugowania moduł, który wygląda tak , jakby zawierał w sobie etree lxml, ale tak naprawdę zawiera ElementTree.
źródło
To wszystko są dobre odpowiedzi. Dodam, że ucząc nowych ludzi programowania w Pythonie, radzenie sobie
import *
jest bardzo trudne. Nawet jeśli Ty lub oni nie napisaliście kodu, nadal jest to przeszkoda.Uczę dzieci (około 8 lat) programowania w Pythonie do manipulowania Minecrafta. Lubię udostępniać im pomocne środowisko programistyczne do pracy z ( Edytor Atom ) i uczyć programowania opartego na REPL (przez bpython ). W Atom stwierdzam, że podpowiedzi / uzupełnienia działają równie skutecznie jak bpython. Na szczęście, w przeciwieństwie do innych narzędzi do analizy statystycznej, Atom nie daje się zwieść
import *
.Jednak weźmy ten przykład ... W tym opakowaniu są
from local_module import *
to zestawy modułów, w tym ta lista bloków . Zignorujmy ryzyko kolizji przestrzeni nazw. Robiącfrom mcpi.block import *
to, sprawiają, że cała lista niejasnych typów bloków jest czymś, na co musisz spojrzeć, aby wiedzieć, co jest dostępne. Gdyby zamiast tego użylifrom mcpi import block
, możesz wpisać,walls = block.
a następnie pojawi się lista autouzupełniania.źródło
Zrozumiałem ważne punkty, które ludzie tutaj umieścili. Mam jednak jeden argument, że czasami „importowanie z gwiazd” nie zawsze może być złą praktyką:
const.py
:import const
, to dla każdej stałej muszę nazywać toconst.SOMETHING
, co prawdopodobnie nie jest najwygodniejszym sposobem.from const import SOMETHING_A, SOMETHING_B ...
, to oczywiście jest to zbyt rozwlekłe i mija się z celem strukturyzacji.from const import *
może być lepszym wyborem.źródło
Jest to bardzo ZŁA praktyka z dwóch powodów:
Do punktu 1 : Zobaczmy przykład w ten sposób:
Tutaj, widząc kod nie będzie dostać pojęcia dotyczące, z którego moduł
b
,c
id
właściwie należy.Z drugiej strony, jeśli robisz to jak:
Jest to dla Ciebie dużo czystsze, a także nowa osoba dołączająca do Twojego zespołu będzie miała lepszy pomysł.
Dla punktu 2 : Powiedzmy oba
module1
imodule2
miej zmienną jakob
. Kiedy robię:Tutaj wartość z
module1
zostaje utracona. Trudno będzie debugować, dlaczego kod nie działa, nawet jeślib
jest zadeklarowany wmodule1
a napisałem kod oczekując, że mój kod będzie używanymodule1.b
Jeśli masz te same zmienne w różnych modułach i nie chcesz importować całego modułu, możesz nawet zrobić:
źródło
W ramach testu utworzyłem moduł test.py z 2 funkcjami A i B, które wypisują odpowiednio „A 1” i „B 1”. Po zaimportowaniu test.py z:
. . . Mogę uruchomić dwie funkcje jako test.A () i test.B (), a „test” pojawia się jako moduł w przestrzeni nazw, więc jeśli edytuję test.py, mogę go ponownie załadować za pomocą:
Ale jeśli wykonam następujące czynności:
nie ma odniesienia do „test” w przestrzeni nazw, więc nie ma możliwości ponownego załadowania go po edycji (o ile wiem), co jest problemem w sesji interaktywnej. Mając na uwadze, że jedno z poniższych:
doda „test” lub „tt” (odpowiednio) jako nazwy modułów w przestrzeni nazw, co pozwoli na ponowne załadowanie.
Jeśli zrobię:
nazwy „A” i „B” pojawiają się w przestrzeni nazw jako funkcje . Jeśli edytuję test.py i powtórzę powyższe polecenie, zmodyfikowane wersje funkcji nie zostaną ponownie załadowane.
Poniższe polecenie wywołuje komunikat o błędzie.
Jeśli ktoś wie jak przeładować moduł załadowany poleceniem „from module import *”, napisz. W przeciwnym razie byłby to kolejny powód, aby unikać formularza:
źródło
Jak sugerowano w dokumentacji, (prawie) nigdy nie powinieneś używać
import *
w kodzie produkcyjnym.Podczas gdy importowanie
*
z modułu jest złe, importowanie * z pakietu jest jeszcze gorsze. Domyślniefrom package import *
importuje wszystkie nazwy zdefiniowane przez pakiet__init__.py
, w tym wszystkie podmoduły pakietu, które zostały załadowane przez poprzednieimport
instrukcje.Jeśli jednak
__init__.py
kod pakietu definiuje listę o nazwie__all__
, przyjmuje się, że jest to lista nazw podmodułów, które powinny zostać zaimportowane pofrom package import *
napotkaniu.Rozważ ten przykład (zakładając, że nie ma
__all__
zdefiniowanej wsound/effects/__init__.py
):Ostatnia instrukcja zaimportuje moduły
echo
isurround
do bieżącej przestrzeni nazw (prawdopodobnie nadpisując poprzednie definicje), ponieważ są one zdefiniowane wsound.effects
pakiecie podczas wykonywaniaimport
instrukcji.źródło