मॉड्यूल आयात समारोह से 'आयात मॉड्यूल' बनाम '


143

मैं हमेशा इस विधि का उपयोग करता रहा हूं:

from sys import argv

और argvसिर्फ argv के साथ उपयोग करें । लेकिन इसका उपयोग करने का एक सम्मेलन है:

import sys

और argv का उपयोग करके sys.argv

दूसरी विधि कोड को स्व दस्तावेज बनाती है और मैं (वास्तव में) इसका पालन ​​करता हूं । लेकिन जिस कारण से मैं पहली विधि पसंद करता हूं वह तेज़ है क्योंकि हम केवल उस फ़ंक्शन को आयात कर रहे हैं जो पूरे मॉड्यूल को आयात करने के बजाय आवश्यक है (जिसमें अधिक बेकार कार्य शामिल हैं जो अजगर उन्हें आयात करने में समय बर्बाद करेगा)। ध्यान दें कि मुझे बस argv की जरूरत है और sys से अन्य सभी कार्य मेरे लिए बेकार हैं।

तो मेरे सवाल हैं। क्या पहला तरीका वास्तव में स्क्रिप्ट को तेज बनाता है? किस विधि को सबसे ज्यादा पसंद किया जाता है? क्यों?



जवाबों:


175

मॉड्यूल आयात करना कुछ भी बर्बाद नहीं करता है ; मॉड्यूल हमेशा पूरी तरह से आयात किया जाता है ( sys.modulesमानचित्रण में), इसलिए आपके द्वारा उपयोग किए जाने वाले तार import sysया from sys import argvबिना किसी बाधा के।

दो बयानों के बीच एकमात्र अंतर यह है कि नाम क्या है; मॉड्यूल import sysमें नाम sysको बांधता है (इसलिए sys-> sys.modules['sys']), मॉड्यूल के अंदर निहित विशेषता पर सीधे इंगित करते हुए from sys import argv, एक अलग नाम बांधता है argv(इसलिए argv-> sys.modules['sys'].argv)। बाकी sysमॉड्यूल अभी भी है, चाहे आप मॉड्यूल से कुछ और उपयोग करें या नहीं।

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

एक या दूसरे के बीच का चुनाव इसके बजाय कोडिंग शैली पर आधारित होना चाहिए ।

एक बड़े मॉड्यूल में, मैं निश्चित रूप से उपयोग करूँगा import sys; कोड प्रलेखन मामले, और sys.argvएक बड़े मॉड्यूल में कहीं का उपयोग करने से यह बहुत स्पष्ट हो जाता है कि आप अभी तक की तुलना में क्या उल्लेख कर रहे हैं argv

यदि आपके द्वारा उपयोग की जाने वाली एकमात्र जगह किसी फ़ंक्शन को कॉल करने के लिए argvकिसी '__main__'ब्लॉक में है main(), from sys import argvतो इसका उपयोग करें यदि आप उस बारे में अधिक खुश महसूस करते हैं:

if __name__ == '__main__':
    from sys import argv
    main(argv)

मैं अभी भी import sysवहाँ खुद का उपयोग करेंगे । सभी चीजें समान (और वे, बिल्कुल, प्रदर्शन और इसे लिखने के लिए उपयोग किए जाने वाले पात्रों की संख्या के संदर्भ में ), कि मेरे लिए आंख पर आसान है।

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

 import somemodule

 def somefunction():
      localname = somemodule.somefunctionorother
      while test:
          # huge, critical loop
          foo = localname(bar)

1
ऐसी स्थिति भी होती है जहां आपके पास उप पैकेज या मॉड्यूल के साथ एक पैकेज होता है जो शीर्ष स्तर के पैकेज में उन सबपैकेज / मॉड्यूल में से एक की विशेषता को उजागर करता है। उपयोग करना from...importआपको इसके package.attributeबजाय अनुमति देता है package.subpackage_or_module.attribute, जो उपयोगी हो सकता है यदि आपके पास पैकेज के भीतर तार्किक या वैचारिक समूह हैं, लेकिन अपने पैकेज के उपयोगकर्ताओं के लिए चीजों को थोड़ा अधिक सुविधाजनक बनाना चाहते हैं। ( numpyकुछ इस तरह से, मुझे विश्वास है।)
जेएबी

Django में आपके पास बहुत सारे स्पॉट हैं जहां चीजें from django.core.management.base import BaseCommandबेहतर हैं, और कुछ भी (विशेष रूप से import django) अपठनीय कोड को जन्म देगा। इसलिए जब मैं इस जवाब को पसंद करता हूं, मुझे लगता है कि कुछ पुस्तकालय (और विशेष रूप से कुछ चौखटे) हैं जिनमें सम्मेलन नंगे आयात का उल्लंघन करना है। हमेशा की तरह, किसी भी स्थिति में जो सबसे अच्छा है उसके बारे में अपने निर्णय का उपयोग करें। लेकिन स्पष्ट के पक्ष में (दूसरे शब्दों में मैं सबसे अधिक भाग के लिए सहमत हूं)।
न्यूरॉनैट

1
@ जेएबी: आप अभी भी import ... asपैकेज को एक अलग नाम से खोजने के लिए उपयोग कर सकते हैं import package.subpackage_or_module as shortname:। from parent import subअनिवार्य रूप से, एक ही बात करता है।
मार्टिज़न पीटरर्स

43

इसके import moduleबजाय उपयोग करने के पक्ष में दो कारण हैं from module import function

पहले नामस्थान है। वैश्विक नाम स्थान जोखिम नाम टकराव में एक समारोह आयात करना।

दूसरा वह मानक मॉड्यूल के लिए प्रासंगिक नहीं है, लेकिन विशेष रूप से विकास के दौरान आपके स्वयं के मॉड्यूल के लिए महत्वपूर्ण है। यह reload()एक मॉड्यूल का विकल्प है । इस पर विचार करो:

from module import func
...
reload(module)
# func still points to the old code

दूसरी ओर

import module
...
reload(module)
# module.func points to the new code

गति के लिए के रूप में ...

हम पूरे मॉड्यूल को आयात करने के बजाय केवल उस फ़ंक्शन को आयात कर रहे हैं (जिसमें अधिक बेकार कार्य शामिल हैं जो अजगर आयात करने को बेकार कर देगा)

चाहे आप एक मॉड्यूल आयात करते हैं या एक मॉड्यूल से एक फ़ंक्शन आयात करते हैं, पायथन पूरे मॉड्यूल को पार्स करेगा। किसी भी तरह से मॉड्यूल आयात किया जाता है। "फ़ंक्शन को आयात करना" फ़ंक्शन को नाम से बांधने से अधिक कुछ नहीं है। वास्तव import moduleमें दुभाषिया की तुलना में कम काम है from module import func


6
रीलोड () पायथन 2 में एक बिलिन था; यह अब अजगर 3 के लिए मामला नहीं है
एंड्रे

मैंने सोचा कि परिपत्र आयात निर्भरता के साथ भी करने के लिए निहितार्थ थे?
ADP

18

from importजब भी यह पठनीयता में सुधार करता है मैं एस का उपयोग करता हूं । उदाहरण के लिए, मुझे पसंद है (अर्धविराम केवल यहाँ स्थान बचाने के लिए हैं):

from collections import defaultdict
from foomodule import FooBar, FooBaz
from twisted.internet.protocol import Factory
defaultdict(); FooBar(); FooBaz(); Factory()

के बजाय:

import collections
import foomodule
import twisted.internet.protocol
collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz()
twisted.internet.protocol.Factory()

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

मैं नियमित रूप से पसंद करता importहूँ अगर मैं एक मॉड्यूल से बहुत सारे छोटे नामों का उपयोग कर रहा हूँ:

import sys
sys.argv; sys.stderr; sys.exit()

या अगर कोई नाम इतना सामान्य है कि उसके नामस्थान के बाहर कोई मतलब नहीं है:

import json
json.loads(foo)

from json import loads
loads(foo)  # potentially confusing

यह मेरा पसंदीदा उत्तर है। 'व्याख्या से बेहतर है स्पष्ट' कभी-कभी पठनीयता, सरलता और DRY के साथ संघर्ष करता है। विशेष रूप से जब Django की तरह एक फ्रेमवर्क का उपयोग कर।
न्यूरोनैट

18

मेरी राय में नियमित उपयोग से importपठनीयता में सुधार होता है। पायथन कोड की समीक्षा करते समय मैं यह देखना पसंद करता हूं कि दिए गए फ़ंक्शन या क्लास सही जगह से आते हैं जहां इसका उपयोग किया जाता है। यह मुझे उस जानकारी को प्राप्त करने के लिए मॉड्यूल के शीर्ष पर स्क्रॉल करने से बचाता है।

लंबे मॉड्यूल नामों के लिए मैं केवल asकीवर्ड का उपयोग करता हूं और उन्हें छोटे उपनाम देता हूं:

import collections as col
import foomodule as foo
import twisted.internet.protocol as twip

my_dict = col.defaultdict()
foo.FooBar()
twip_fac = twip.Factory()

एक अपवाद के रूप में मैं हमेशा मॉड्यूल के from module import somethingसाथ व्यवहार करते समय संकेतन का उपयोग करता हूं __future__। आप इसे दूसरे तरीके से नहीं कर सकते हैं जब आप चाहते हैं कि सभी तार पायथन 2 में डिफ़ॉल्ट रूप से यूनिकोड हो जाएं, जैसे

from __future__ import unicode_literals
from __future__ import print_function

तथास्तु! "आयात के रूप में" एक विजेता संयोजन है :-)
पज

4

हालाँकि import sysऔर from sys import agrvदोनों पूरे sysमॉड्यूल को आयात करते हैं , बाद वाला नाम बाइंडिंग का उपयोग करता है इसलिए केवल argvमॉड्यूल बाकी कोड के लिए सुलभ है।

कुछ लोगों के लिए यह पसंदीदा शैली होगी क्योंकि यह केवल आपके द्वारा स्पष्ट रूप से बताए गए फ़ंक्शन को सुलभ बनाता है।

यह हालांकि संभावित नाम संघर्ष का परिचय देता है। क्या होगा यदि आपके पास एक और मॉड्यूल नाम था argv? ध्यान दें कि आप फ़ंक्शन को स्पष्ट रूप से आयात कर सकते हैं और नाम बदल सकते हैं from sys import argv as sys_argv, एक कन्वेंशन जो स्पष्ट आयात को पूरा करता है और नाम स्थान टकराव की संभावना कम है।


2
तो इससे if sys_argv:बेहतर कोई कैसे हो सकता है if sys.argv:? मुझे पता है कि दूसरे कथन का क्या मतलब है, मुझे पता नहीं है कि विचित्र आयात को पीछे किए बिना पहला रूप क्या है।
msw

1

मैंने हाल ही में यह सवाल खुद से पूछा। मैंने अलग-अलग तरीकों से समय निकाला।

पुस्तकालय का अनुरोध करता है

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

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

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

एसआईएस लाइब्रेरी

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

मुझे ऐसा लगता है कि वहाँ प्रदर्शन में एक मामूली अंतर।


आप एक विशेषता लुकअप में जोड़ रहे हैं। तुलना करने के लिए import moduleके साथ from module import nameसही ढंग से, जोड़ने के लिए उस नाम देखने import moduleमामले। उदाहरण के लिए लाइन जोड़ने sys.argvके लिए arपरीक्षण, आदि अभी भी एक अंतर हो जाएगा, क्योंकि काम किया है थोड़ा , अलग रूप में विभिन्न बाईटकोड उत्पन्न होता है और अलग अलग codepaths क्रियान्वित कर रहे हैं।
Martijn Pieters

2
ध्यान दें कि मैं सीधे अपने उत्तर में उस अंतर को संबोधित करता हूं; वहाँ का उपयोग कर के बीच एक अंतर हो जाएगा import sysतो का उपयोग कर sys.argvएक पाश में समय के हजारों बनाम from sys import argvतो बस का उपयोग कर argv। लेकिन तुम नहीं। अपने मॉड्यूल के वैश्विक स्तर पर आप केवल एक बार करते हैं, आपको वास्तव में पठनीयता के लिए अनुकूलन करना चाहिए, समय में सूक्ष्म अंतर नहीं।
मार्टिज़न पीटर्स

1
Ahhhh! और मुझे लगा कि मैं किसी चीज़ पर हूँ! :) मैंने केवल आपके उत्तर को स्किम्ड किया। लगता है कि मैं उस पर बंदूक कूद गया। अच्छा लगता है दीन होना।
tmthyjames 16

-1

प्रकाशित कोड अंशों को देखते हुए, पूरे मॉड्यूल को आयात करना और संदर्भित करना module.functionबहुत मानक है, कम से कम मानक मॉड्यूल के लिए। एक अपवाद प्रतीत होता हैdatetime

from datetime import datetime, timedelta

तो आप के datetime.now()बजाय कह सकते हैं datetime.datetime.now()

यदि आप प्रदर्शन के बारे में चिंतित हैं, तो आप हमेशा कह सकते हैं (उदाहरण के लिए)

argv = sys.argv

मॉड्यूल लुकअप होने के बाद से आपका प्रदर्शन महत्वपूर्ण है। हालाँकि, यह फ़ंक्शन / विधियों के साथ काम करेगा, अधिकांश IDE भ्रमित हो जाएगा और फ़ंक्शन के लिए स्रोत लिंक / हस्ताक्षर प्रदर्शित नहीं करेगा (उदाहरण के लिए) जब इसे किसी चर में असाइन किया जाता है।


-2

मैं सिर्फ यह जोड़ना चाहता हूं कि अगर आप कुछ ऐसा करते हैं

from math import sin

(या किसी अन्य अंतर्निहित लाइब्रेरी जैसे sysया posix), तो sinआपके मॉड्यूल के लिए दस्तावेज़ीकरण में शामिल किया जाएगा (यानी जब आप ऐसा करते हैं । >>> help(mymodule)या इससे $ pydoc3 mymoduleबचने के लिए, आयात का उपयोग करें:

import math
from math import sin as _sin

पुनश्च: एक अंतर्निहित पुस्तकालय वह है जो सी कोड से संकलित है और पायथन के साथ शामिल है। argparse, osऔर ioअंतर्निहित पैकेज नहीं हैं

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