"आयात *" बुरा क्यों है?


153

यह import *पायथन में उपयोग नहीं करने के लिए सिफारिश की है ।

क्या कोई इसके लिए कारण साझा कर सकता है, ताकि मैं अगली बार ऐसा करने से बच सकूं?


3
डुप्लिकेट: stackoverflow.com/questions/2360724/…
S.Lott

2
यह निर्भर करता है कि यदि आप स्क्रिप्टिंग या कोड लिख रहे हैं तो आपको पुन: उपयोग करने की आवश्यकता है। यह कभी-कभी कोड मानकों को अनदेखा करने के लिए भुगतान करता है। "आयात *" भी ठीक हो सकता है यदि आपके पास एक नामकरण सम्मेलन है जो यह स्पष्ट करता है कि सामान कहां से आया है। जैसे "कैट्स इंपोर्ट * से; टैबीकैट; मेनकूनकैट; केलिकोकाट;"
गाटाटिग्रादो

3
import *मेरे लिए पायथन 2 या 3 में पहले स्थान पर काम नहीं करता है
joshreesjones

1
क्या इससे आपके सवाल का जवाब मिलता है? क्या वास्तव में "आयात *" आयात करता है?
एएमसी

जवाबों:


223
  • क्योंकि यह आपके नाम स्थान में बहुत अधिक सामान डालता है (पिछले आयात से किसी अन्य वस्तु को छाया कर सकता है और आपको इसके बारे में पता नहीं होगा)।

  • क्योंकि आपको पता नहीं है कि क्या आयात किया गया है और आसानी से पता नहीं चल सकता है कि किस मॉड्यूल से एक निश्चित चीज आयात की गई थी (पठनीयता)।

  • क्योंकि आप pyflakesअपने कोड में त्रुटियों का पता लगाने के लिए जैसे कूल टूल्स का उपयोग नहीं कर सकते हैं।


2
हाँ, मुझे वास्तव में अपनी नौकरी से नफरत है जब कोई व्यक्ति * आयात का उपयोग करता है, क्योंकि तब मैं सिर्फ पाइफ्लेक्स नहीं चला सकता और खुश रह सकता हूं, लेकिन उन आयातों को सुधारना होगा। यह अच्छा है, हालांकि, उस pyflakes के साथ मेरी मदद करता है :-)
gruszczy

7
एक ठोस उदाहरण के रूप में, NumPy के कई उपयोगकर्ताओं को numpy.anyछायांकन द्वारा काट लिया गया है anyजब वे करते हैं from numpy import *या "सहायक" उपकरण उनके लिए करता है।
user2357112

1
क्या मुझे समान कारणों से IPython के लिए -pylab स्विच का उपयोग करने से बचना चाहिए?
टाइमजैब

6
एक जोखिम को उजागर करने के लिए, मैंने इसे पढ़ने से पहले कभी नहीं सोचा था ("पिछले आयात से कुछ अन्य वस्तु को छाया दे सकता है"): बयानों import *के क्रम को importमहत्वपूर्ण बनाता है ... यहां तक ​​कि मानक पुस्तकालय मॉड्यूल के लिए भी जो सामान्य रूप से आयात के आदेश की परवाह नहीं करते हैं । आपके importबयानों की वर्णमाला के रूप में निर्दोष कुछ भी आपकी स्क्रिप्ट को तोड़ सकता है जब आयात युद्ध के एक पूर्व हताहत एकमात्र उत्तरजीवी हो जाता है। (यहां तक ​​कि अगर आपकी स्क्रिप्ट अब काम करती है और कभी नहीं बदलती है, तो यह कुछ समय बाद अचानक विफल हो सकता है यदि आयातित मॉड्यूल एक नया नाम पेश करता है जो आपके द्वारा भरोसा किए जाने वाले को बदल देता है।)
केविन जे। चेस

49

अजगर के ज़ेन के अनुसार :

निहितार्थ की तुलना में स्पष्ट है।

... उस के साथ बहस नहीं कर सकते, निश्चित रूप से?


29
दरअसल, आप इससे बहस कर सकते हैं। यह भी पूरी तरह से असंगत है, यह देखते हुए कि आप पायथन में स्पष्ट रूप से चर घोषित नहीं करते हैं, जब आप उन्हें असाइन करते हैं तो वे बस अस्तित्व में आते हैं।
कोनराड रूडोल्फ

7
@gruszczy: घोषित चर क्या बेमानी है ? नियत? नहीं, यह दो अलग अवधारणा है और कुछ घोषित करना एक बहुत ही विशिष्ट और महत्वपूर्ण जानकारी बताता है। वैसे भी, खोजकर्ता हमेशा कुछ हद तक अतिरेक से जुड़ा होता है, वे एक ही सिक्के के दो चेहरे होते हैं।
कोनराड रुडोल्फ

3
@kriss सही, लेकिन वह मेरी बात नहीं थी। मेरा कहना था कि एक चर को स्पष्ट रूप से घोषित करने में विफलता त्रुटियों की ओर ले जाती है। आप कहते हैं कि "घोषणा के बिना काम करना असंभव है"। लेकिन यह गलत है, मेरा पूरा कहना यह है कि पायथन दुर्भाग्य से ठीक ऐसा ही करता है।
कोनराड रुडोल्फ

3
@kriss एक और घोषणा से संकलक दी गई जानकारी का टुकड़ा तथ्य यह है कि आप वास्तव में एक नया वेरिएबल की घोषणा करने का इरादा है। यह प्रकार प्रणाली के लिए जानकारी का एक महत्वपूर्ण टुकड़ा है। आप कहते हैं कि आधुनिक IDE गलत तरीके से होने वाली समस्या को हल करते हैं, लेकिन यह केवल गलत है, और वास्तव में गैर संवैधानिक रूप से संकलित भाषाओं में एक पर्याप्त समस्या है, यही वजह है कि पर्ल को जोड़ा गया use strict(जावास्क्रिप्ट var)। एक तरफ के रूप में, निश्चित रूप से पायथन टाइपलेस नहीं है (यह वास्तव में दृढ़ता से टाइप किया गया है)। वैसे भी, भले ही आप सही थे, यह अभी भी इस जवाब में उद्धृत, पायथन के ज़ेन के विपरीत होगा।
कोनराड रुडोल्फ

3
@kriss आप इसे गलत है: एक ही चर पुन: उपयोग नाम नहीं एक समस्या है - एक ही पुन: उपयोग चर है (यानी एक ही दायरे में एक ही नाम)। स्पष्ट घोषणाएं वास्तव में इस गलती को रोकेंगी (और अन्य, साधारण गलत व्यवहार के आधार पर, जो मैंने कहा है, वास्तव में एक अत्यंत सामान्य और समय लेने वाली समस्या है, भले ही आप सही हों कि समस्या पर्ल-लाइक में बड़ी है भाषाओं)। और जो विरोधाभास मुझे पता चला है, वह है गवाहों की खोज के लिए ज़ेन की आवश्यकता, जो शारीरिक रूप से यहाँ खिड़की से बाहर फेंक दिया गया है।
कोनराड रुडोल्फ

40

आप **locals()कार्यों के लिए पास नहीं हैं , क्या आप?

के बाद से अजगर एक "शामिल हैं" बयान का अभाव है, औरself पैरामीटर स्पष्ट है, और देखते हुए नियम काफी सरल हैं, यह आम तौर पर एक चर पर एक उंगली बिंदु और बताने के लिए जहां उस वस्तु से आता है बहुत आसान है - अन्य मॉड्यूल पढ़ने के बिना और किसी भी प्रकार के बिना आईडीई (जो कि वैसे भी आत्मनिरीक्षण के रास्ते में सीमित हैं, इस तथ्य से कि भाषा बहुत गतिशील है)।

जो import *सब तोड़ता है।

इसके अलावा, इसमें बग को छिपाने की एक ठोस संभावना है।

import os, sys, foo, sqlalchemy, mystuff
from bar import *

अब, यदि बार मॉड्यूल में " os", " mystuff", आदि ... विशेषताओं में से कोई भी है, तो वे स्पष्ट रूप से आयातित वाले को ओवरराइड करेंगे, और संभवतः बहुत अलग चीजों को इंगित करेंगे। परिभाषित __all__पट्टी में अक्सर बुद्धिमान है - यह राज्यों परोक्ष आयात किया जाएगा क्या है - लेकिन अभी भी यह पता लगाने के लिए मुश्किल है जहां वस्तुओं, से आते हैं पढ़ने और बार मॉड्यूल पार्स करने और निम्नलिखित के बिना अपने आयात। import *जब मैं किसी प्रोजेक्ट का स्वामित्व लेता हूं, तो उसका एक नेटवर्क पहली चीज है जिसे मैं ठीक करता हूं।

मुझे गलत न समझें: यदि import *वे गायब थे, तो मैं इसे करने के लिए रोऊंगा। लेकिन इसका उपयोग सावधानी से करना होगा। एक अन्य मॉड्यूल पर एक मुखौटा इंटरफ़ेस प्रदान करने के लिए एक अच्छा उपयोग मामला है। इसी तरह, सशर्त आयात बयानों का उपयोग, या फ़ंक्शन / वर्ग नामस्थान के अंदर आयात, अनुशासन की एक बिट की आवश्यकता है।

मुझे लगता है कि मध्यम-से-बड़ी परियोजनाओं में, या कई योगदानकर्ताओं के साथ छोटे, सांख्यिकीय विश्लेषण के संदर्भ में न्यूनतम स्वच्छता की आवश्यकता होती है - कम से कम pyflakes या इससे भी बेहतर रूप से कॉन्फ़िगर किया गया पाइलिंट - कई तरह के कीड़े पकड़ने के लिए वे होते हैं।

बेशक यह अजगर है - नियमों को तोड़ने के लिए स्वतंत्र महसूस करें, और पता लगाने के लिए - लेकिन उन परियोजनाओं से सावधान रहें जो दस गुना बढ़ सकती हैं, अगर स्रोत कोड अनुशासन गायब है तो यह एक समस्या होगी।


6
अजगर 2.x करता है एक "शामिल हैं" बयान की है। इसे कहते हैं execfile()। सौभाग्य से, यह शायद ही कभी इस्तेमाल किया और 3.x में चला गया।
स्वेन मार्नाच

**vars()अगर ग्लोबल्स किसी अन्य फ़ाइल में है तो ग्लोबल्स को कैसे शामिल करें ? : पी
सोलोमन उको

16

from ... import *एक इंटरैक्टिव सत्र में करना ठीक है ।


कैसे एक doctestस्ट्रिंग के अंदर ? क्या import *इस मामले में "सैंडबॉक्स" के अंदर व्याख्या की जाती है? धन्यवाद।
पैट्रिक

16

ऐसा इसलिए है क्योंकि आप नाम स्थान को प्रदूषित कर रहे हैं। आप सभी कार्यों और कक्षाओं को अपने नामस्थान में आयात करेंगे, जो आपके द्वारा परिभाषित कार्यों के साथ टकरा सकते हैं।

इसके अलावा, मुझे लगता है कि रखरखाव कार्य के लिए एक योग्य नाम का उपयोग करना अधिक स्पष्ट है; आप कोड लाइन पर ही देखते हैं कि कोई फ़ंक्शन कहाँ से आता है, इसलिए आप डॉक्स को अधिक आसानी से देख सकते हैं।

मॉड्यूल फू में:

def myFunc():
    print 1

आपके कोड में:

from foo import *

def doThis():
    myFunc() # Which myFunc is called?

def myFunc():
    print 2


9

मान लें कि आपके पास foo नामक एक मॉड्यूल में निम्नलिखित कोड है:

import ElementTree as etree

और फिर आपके अपने मॉड्यूल में:

from lxml import etree
from foo import *

अब आपके पास एक कठिन-से-डिबग मॉड्यूल है जो दिखता है कि इसमें lxml का एट्री है, लेकिन वास्तव में इसके बजाय ElementTree है।


7

ये सभी अच्छे उत्तर हैं। मैं जोड़ना चाहता हूं कि जब नए लोगों को पायथन में कोड करना सिखाया जाता है, तो इससे निपटना import *बहुत मुश्किल होता है। यहां तक ​​कि अगर आप या उन्होंने कोड नहीं लिखा है, यह अभी भी एक ठोकर है।

मैं बच्चों (लगभग 8 वर्ष की उम्र) को पाइनकॉन में कार्यक्रम करने के लिए सिखाता हूं। मैं उन्हें ( एटम संपादक ) के साथ काम करने और REPL- संचालित विकास ( bpython के माध्यम से ) सिखाने के लिए एक उपयोगी कोडिंग वातावरण देना पसंद करता हूं । एटम में मुझे पता चलता है कि संकेत / पूरा होने के रूप में प्रभावी रूप से bpython के रूप में काम करता है। सौभाग्य से, कुछ अन्य सांख्यिकीय विश्लेषण उपकरणों के विपरीत, एटम द्वारा मूर्ख नहीं बनाया गया है import *

हालांकि, इस उदाहरण को लेने देता है ... इस आवरण में वे ब्लॉकों की इस सूचीfrom local_module import * सहित एक गुच्छा मॉड्यूल हैं । आइए नाम स्थान टकराव के जोखिम को अनदेखा करें। ऐसा करने से वे अस्पष्ट प्रकार के ब्लॉक की इस पूरी सूची को बनाते हैं, जिसे देखने के लिए आपको यह जानना होगा कि क्या उपलब्ध है। यदि वे इसके बजाय इस्तेमाल किया गया था , तो आप टाइप कर सकते हैं और फिर एक स्वत: पूर्ण सूची पॉप अप होगी। from mcpi.block import *from mcpi import blockwalls = block.Atom.io स्क्रीनशॉट


6

लोगों द्वारा यहां लगाए गए मान्य बिंदुओं को समझें। हालांकि, मेरा एक तर्क है कि, कभी-कभी, "स्टार आयात" हमेशा एक बुरा अभ्यास नहीं हो सकता है:

  • जब मैं अपने कोड को इस तरह से संरचना करना चाहता हूं कि सभी स्थिरांक एक मॉड्यूल में जाएं const.py:
    • यदि मैं करता हूं import const, तो प्रत्येक स्थिर के लिए, मुझे इसे संदर्भित करना होगा const.SOMETHING, जो शायद सबसे सुविधाजनक तरीका नहीं है।
    • यदि मैं करता हूं from const import SOMETHING_A, SOMETHING_B ..., तो जाहिर है कि यह बहुत अधिक क्रियात्मक है और संरचना के उद्देश्य को हरा देता है।
    • इस प्रकार मुझे लगता है कि इस मामले में, from const import *एक बेहतर विकल्प हो सकता है।

4

यह दो कारणों से एक बहुत ही बुरा अभ्यास है:

  1. कोड पठनीयता
  2. चर / कार्यों आदि को ओवरराइड करने का जोखिम

के लिए बिंदु 1 : आइए इस का एक उदाहरण देखें:

from module1 import *
from module2 import *
from module3 import *

a = b + c - d

यहां, कोड को देखने पर किसी को पता नहीं चलेगा कि कौन से मॉड्यूल से संबंधित है b, cऔर dवास्तव में संबंधित है।

दूसरे तरीके पर, अगर आप इसे पसंद करते हैं:

#                   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

यह आपके लिए बहुत साफ है, और आपकी टीम में शामिल होने वाले नए व्यक्ति के पास भी बेहतर विचार होगा।

के लिए बिंदु 2 : Let दोनों का कहना है कि module1और module2के रूप में चर राशि b। जब मैं करता हूं:

from module1 import *
from module2 import *

print b  # will print the value from module2

यहां से मूल्य module1खो गया है। यह डिबग करना कठिन होगा कि कोड bघोषित होने पर भी क्यों काम नहीं कर module1रहा है और मैंने कोड लिखा है, मेरे कोड का उपयोग करने की अपेक्षा कर रहा हैmodule1.b

यदि आपके पास अलग-अलग मॉड्यूल में समान चर हैं, और आप पूरे मॉड्यूल को आयात नहीं करना चाहते हैं, तो आप भी कर सकते हैं:

from module1 import b as mod1b
from module2 import b as mod2b

2

परीक्षण के रूप में, मैंने 2 फ़ंक्शन ए और बी के साथ एक मॉड्यूल टेस्टहोम बनाया, जो क्रमशः "ए 1" और "बी 1" प्रिंट करता है। के साथ test.py आयात करने के बाद:

import test

। । । मैं परीक्षण के रूप में 2 फ़ंक्शन चला सकता हूं। () और test.B (), और "परीक्षण" नामस्थान में एक मॉड्यूल के रूप में दिखाता है , इसलिए यदि मैं test.py संपादित करता हूं तो मैं इसे फिर से लोड कर सकता हूं:

import importlib
importlib.reload(test)

लेकिन अगर मैं निम्नलिखित कार्य करता हूं:

from test import *

नामस्थान में "परीक्षण" का कोई संदर्भ नहीं है, इसलिए एक संपादन के बाद इसे फिर से लोड करने का कोई तरीका नहीं है (जहां तक ​​मैं बता सकता हूं), जो एक इंटरैक्टिव सत्र में एक समस्या है। जबकि दोनों में से कोई भी:

import test
import test as tt

नेमस्पेस में मॉड्यूल नामों के रूप में "परीक्षण" या "टीटी" (क्रमशः) जोड़ देगा, जो फिर से लोड करने की अनुमति देगा।

यदि मैं करता हूँ:

from test import *

नाम "ए" और "बी" नाम फ़ंक्शन में फ़ंक्शन के रूप में दिखाई देते हैं । यदि मैं test.py संपादित करता हूं, और उपरोक्त आदेश को दोहराता हूं, तो फ़ंक्शन के संशोधित संस्करण पुनः लोड नहीं होते हैं।

और निम्न कमांड एक त्रुटि संदेश प्राप्त करता है।

importlib.reload(test)    # Error - name 'test' is not defined

यदि कोई जानता है कि "मॉड्यूल आयात *" से लोड किए गए मॉड्यूल को कैसे फिर से लोड करना है, तो कृपया पोस्ट करें। अन्यथा, यह फ़ॉर्म से बचने का एक और कारण होगा:

from module import *

2

डॉक्स में सुझाव दिया गया है, आपको import *उत्पादन कोड में कभी भी (लगभग) उपयोग नहीं करना चाहिए ।

जबकि मॉड्यूल* से आयात करना बुरा है, पैकेज से * आयात करना और भी बुरा है। डिफ़ॉल्ट रूप से, पैकेज द्वारा किसी भी नाम को परिभाषित किया जाता है , जिसमें पैकेज के किसी भी सबमॉड्यूल शामिल हैं जो पिछले बयानों द्वारा लोड किए गए थे ।from package import *__init__.pyimport

हालाँकि, यदि किसी पैकेज का __init__.pyकोड नाम की सूची को परिभाषित करता है __all__, तो इसे सबमॉड्यूल नामों की सूची के रूप में लिया जाता है जिन्हें from package import *सामना करने पर आयात किया जाना चाहिए ।

इस उदाहरण पर विचार करें (यह मानते हुए कि इसमें कोई __all__परिभाषित नहीं है 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 *

अंतिम विवरण वर्तमान नामस्थान (संभवतः पिछली परिभाषाओं को ओवरराइड करने) में मॉड्यूल echoऔर आयात करेगा surroundक्योंकि sound.effectsजब वे importविवरण निष्पादित होते हैं तो पैकेज में परिभाषित किए जाते हैं ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.