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?
import *
u mnie nie działa na pierwszym miejscu w Pythonie 2 lub 3.
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?
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.
numpy.any
cieniowanie, any
kiedy to robią, from numpy import *
lub „pomocne” narzędzie robi to za nich.
import *
sprawia, że kolejność tych import
wypowiedzi znaczących ... nawet dla standardowych modułów bibliotecznych, które zazwyczaj nie dbają o celu importu . Coś tak niewinnego, jak alfabetowanie import
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ś.)
use strict
(JavaScript var
). 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, aself
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.
import os, sys, foo, sqlalchemy, mystuff
from bar import *
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.
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? : P
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:
def myFunc():
print 1
W swoim kodzie:
from foo import *
def doThis():
myFunc() # Which myFunc is called?
def myFunc():
print 2
http://docs.python.org/tutorial/modules.html
Zauważ, że generalnie praktyka importowania
*
z modułu lub pakietu jest źle widziana, ponieważ często powoduje to słabo czytelny kod .
Powiedzmy, że masz następujący kod w module o nazwie foo:
import ElementTree as etree
a następnie we własnym module masz:
from lxml import etree
from foo import *
Masz teraz trudny do debugowania moduł, który wygląda tak , jakby zawierał w sobie etree lxml, ale tak naprawdę zawiera ElementTree.
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ąc from 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żyli from mcpi import block
, możesz wpisać, walls = block.
a następnie pojawi się lista autouzupełniania.
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ć to const.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.Jest to bardzo ZŁA praktyka z dwóch powodów:
Do punktu 1 : Zobaczmy przykład w ten sposób:
from module1 import *
from module2 import *
from module3 import *
a = b + c - d
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:
# v v will know that these are from module1
from module1 import b, c # way 1
import module2 # way 2
a = b + c - module2.d
# ^ will know it is from module2
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
i module2
miej zmienną jako b
. Kiedy robię:
from module1 import *
from module2 import *
print b # will print the value from module2
Tutaj wartość z module1
zostaje utracona. Trudno będzie debugować, dlaczego kod nie działa, nawet jeśli b
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ć:
from module1 import b as mod1b
from module2 import b as mod2b
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:
import test
. . . 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ą:
import importlib
importlib.reload(test)
Ale jeśli wykonam następujące czynności:
from test import *
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:
import test
import test as tt
doda „test” lub „tt” (odpowiednio) jako nazwy modułów w przestrzeni nazw, co pozwoli na ponowne załadowanie.
Jeśli zrobię:
from test import *
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.
importlib.reload(test) # Error - name 'test' is not defined
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:
from module import *
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ślnie from package import *
importuje wszystkie nazwy zdefiniowane przez pakiet __init__.py
, w tym wszystkie podmoduły pakietu, które zostały załadowane przez poprzednie import
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 po from package import *
napotkaniu.
Rozważ ten przykład (zakładając, że nie ma __all__
zdefiniowanej w sound/effects/__init__.py
):
# anywhere in the code before import *
import sound.effects.echo
import sound.effects.surround
# in your module
from sound.effects import *
Ostatnia instrukcja zaimportuje moduły echo
i surround
do bieżącej przestrzeni nazw (prawdopodobnie nadpisując poprzednie definicje), ponieważ są one zdefiniowane w sound.effects
pakiecie podczas wykonywania import
instrukcji.