2012-07-07 8 views
9

मुझे बस अपना समय बर्बाद करने का इरादा नहीं है, लेकिन यह आपके लिए भी हुआ है, जबकि पाइथन के with कथन का उपयोग करते हुए यह वास्तव में "5 वीं पंक्ति" पाइथन का जेन "वह जाता है" फ्लैट नेस्टेड से बेहतर है "? क्या कोई प्रबुद्ध पायथन गुरु मुझे इस पर कुछ अंतर्दृष्टि साझा कर सकता है?पाइथन बनाम जेन के जेन - दार्शनिक सोच

(मैं हमेशा लगता है कि खरोज का एक और स्तर हर बार जब मैं f.close() के बजाय with का उपयोग अपने कोड में पॉप अप होता है ... और यह की तरह नहीं है मैं वैसे भी उपयोग नहीं करने वाले try: ... finally: ... और अभी भी with के इस प्रकार के लाभ कर रहा हूँ मुझे टलना, यहां तक ​​कि के रूप में मैं अजगर की तरह और समझने के लिए अधिक से अधिक बड़े होते हैं ...)


@glglgl (क्षमा करें, मैं टिप्पणी में कोड लिखने के लिए एक रास्ता) नहीं मिल सकता है: हाँ, लेकिन अगर आप with रास्ते पर जाते हैं, आपका कोड बन जाता है:

try: 
    with file(...) as f: 
     ... 
except IOError: 
    ... 

... और try के बिना बस उपयोग करने वाले लोग हैकी "एक उपयोग" कोड के प्रकार में क्या कर रहे हैं, जहां वे किसी भी तरह से f.close() का उपयोग करते हैं (जो खराब है क्योंकि फ़ाइल बंद नहीं हो सकती है उनके f.close() से पहले एक अपवाद फेंक दिया जाता है), इसलिए "हैकी" कोड के लिए लोग with का उपयोग नहीं करते हैं, क्योंकि मुझे नहीं पता, मुझे लगता है कि वे इसे "फैंसी" ढूंढते हैं और अच्छी तरह से संरचित कोड के लिए यह नहीं लाता है वैसे भी कोई लाभ, तो ऐसा लगता है कि इसके लिए कोई वास्तविक दुनिया उपयोग नहीं है ... यह वास्तव में मेरे बारे में सोच रहा था।

+1

अधिकांश समय मैं सिर्फ आईओइरर को प्रचारित करता हूं और इसे कहीं और पकड़ता हूं। – Dikei

+0

जितना मैं इस प्रश्न के आधार पर असहमत हूं, मुझे आपको वापस जाने और पीईपी को फिर से पढ़ने के लिए प्रस्ताव देना है [342] (http: //www.python।संगठन/देव/पेप्स/पेप -0342 /) और [343] (http://www.python.org/dev/peps/pep-0343/) – kojiro

उत्तर

5

हां, The Zen of Python कहता है "फ्लैट नेस्टेड से बेहतर है", हालांकि यह एकमात्र विशेषता नहीं है जिसे हम परवाह करते हैं; यह भी कहता है "सरल जटिल से बेहतर है"। with की सुंदरता यह है कि यह वास्तव में नीचे बताए गए दोनों सिद्धांतों के का पालन करती है।

किसी भी समय जब आप पाइथन में एक विशेषता के बारे में दार्शनिक सोच में खुद को पाते हैं तो यह सुविधा के पीछे प्रेरणा के बारे में पढ़ने के लिए Python Enhancement Proposals (PEPs) को देखने लायक है। इस मामले में PEP 343 -- The "with" Statement यह कहता है कि सार में सामने:

यह पीईपी यह कोशिश/अंत में बयान के मानक का उपयोग करता है बाहर कारक संभव बनाने के लिए पायथन भाषा के लिए "के साथ" एक नया बयान कहते हैं।

try/finally स्टेटमेंट्स फैक्टरिंग कोड को सरल और अधिक पठनीय बनाता है।

PEP 343 कुछ सरल वाक्य रचनात्मक चीनी प्रदान करने से गहरा हो जाता है।

अभिव्यक्ति तुरंत बयान में कीवर्ड के साथ निम्नलिखित एक "संदर्भ अभिव्यक्ति" के रूप में है कि अभिव्यक्ति क्रम पर्यावरण संदर्भ प्रबंधक के लिए स्थापित करता के रूप में मुख्य सुराग प्रदान करता है: यह एक संदर्भ प्रबंधक प्रोटोकॉल स्थापित करता है बयान शरीर की अवधि।

संदर्भ प्रबंधक प्रोटोकॉल का उपयोग करके, एपीआई लेखकों जटिलता को छिपाने में मदद कर सकते हैं और बहु-थ्रेडेड संदर्भ में संसाधनों का सही अधिग्रहण/रिलीज सुनिश्चित कर सकते हैं।

लेकिन with बयान का असली सुंदरता PEP 343 का उदाहरण 12 जो बताते हैं कि में दिखाया गया है:

ए 'नेस्ट "संदर्भ प्रबंधक कि स्वचालित रूप से से आपूर्ति की संदर्भों घोंसले बाएँ-से-सही से बचने के लिए अत्यधिक इंडेंटेशन

का उपयोग nested() संदर्भ प्रबंधक आप कोड है कि इस तरह दिखता है ले जा सकते हैं:

with a as x: 
    with b as y: 
     with c as z: 
      # Perform operation 

और यह इस में बदल जाते हैं:

with nested(a, b, c) as (x, y, z): 
      # Perform operation 

ध्यान दें कि nested() अजगर 2.5 में पेश किया गया था, लेकिन संस्करण 2.7 के रूप में इसे इस एकाधिक संदर्भ प्रबंधक वाक्य रचनात्मक रूप के पक्ष में बहिष्कृत किया गया है:

with a as x, b as y, c as z: 
      # Perform operation 

स्पष्ट रूप से न केवल यह आसान और अधिक पठनीय है, लेकिन यह घोंसला से कहीं अधिक सपाट है। है आप एक बार में एक से अधिक फ़ाइल को खोलने के लिए कई संदर्भ प्रबंधकों का उपयोग कर सकते हैं, जब आप ज़िप करना चाहते का एक उदाहरणcomments on Simeon Visser's answer यहां के जवाब में: इस प्रकार, with का उपयोग करने का 無爲 :)

अद्यतन मार्ग का अनुसरण है दो (या अधिक) एक साथ इस तरह खोलने यदि फ़ाइलों में से एक में विफल रहता है कि यह पूरी बात असफल और ठीक से प्रत्येक फ़ाइल खोला गया था बंद कर देगा फ़ाइलों की सामग्री: दो बार

from itertools import izip 
with open("/etc/passwd") as a, open("/etc/group") as b, open("/etc/shadow") as c: 
    for lines in izip(a,b,c): 
     print map(lambda x: x.split(':')[0], lines) 

भागो इस उदाहरण; एक बार रूट के रूप में और एक बार सामान्य उपयोगकर्ता के रूप में। मान लें कि आप इस फ़ाइल को ziptogether.py के रूप में सहेजते हैं, इसे पहले sudo python ziptogether.py के साथ रूट के रूप में आमंत्रित करने का प्रयास करें और यह सफल होगा, लेकिन इसे python ziptogether.py के साथ सामान्य उपयोगकर्ता के रूप में आमंत्रित करना विफल हो जाएगा क्योंकि आपके पास /etc/shadow पढ़ने की अनुमति नहीं है। जब यह विफल रहता है तो संदर्भ प्रबंधक यह सुनिश्चित करेगा कि विफलता से पहले सफलतापूर्वक खोले गए फ़ाइलों को with कथन के दायरे से बाहर चलाए जाने पर ठीक से बंद कर दिया गया है।

+1

कुडोस। सुंदर और सूचनात्मक जवाब! – NeuronQ

+1

@NeuronQ मैंने अपने उत्तर को यह नोट करने के लिए अपडेट किया कि 'नेस्टेड()' को बहिष्कृत किया गया है और एकाधिक संदर्भ प्रबंधकों के लिए एक सरल सिंटैक्टिक रूप भी है। – aculich

7

आप यह पहले से ही उल्लेख: यह सिर्फ फ़ाइल आपरेशन के बाद बंद की तुलना में

f = file(...) 
try: 
    # do work on file 
finally: 
    f.close() 

करने के लिए क्लीनर है - जो एक अपवाद तब होता है, तो पहुँच नहीं किया जाएगा।

यदि आप try/finally से with की तुलना करते हैं, तो आपके पास इंडेंटेशन का एक ही स्तर है, इसलिए आप कुछ भी नहीं खोते हैं। यदि, हालांकि, आप अपवाद हैंडलिंग करते हैं, तो आपके पास इंडेंटेशन का एक और स्तर है, जो वास्तव में ज़ेन पॉइंट के खिलाफ है।

ओटीओएच, with चीजों को समाहित करता है और उन्हें आसानी से और अधिक पठनीय बनाता है, जो अन्य ज़ेन पहलुओं हैं।

मेरे लिए हमेशा हर ज़ेन पहलू का पालन करना असंभव लगता है; कभी-कभी आपको दूसरे के खिलाफ वजन करना पड़ता है। इस मामले में, आप इंडेंटेशन के एक स्तर को "खो देते हैं", लेकिन आपको बेहतर पठनीयता और रखरखाव मिलती है। उत्तरार्द्ध मेरे लिए एक लाभ प्रतीत होता है।

+0

मैंने आपको जवाब देने का प्रयास किया लेकिन लिखने का कोई तरीका नहीं मिला टिप्पणियों में कोड इसलिए मैंने आपके प्रश्न – NeuronQ

+0

@NeuronQ के नीचे मेरा जवाब जोड़ा, मैंने जवाब – glglgl

+0

अपडेट किया है। मैं सहमत हूं: जेन ऑफ पायथन के तत्वों को अक्सर एक दूसरे के खिलाफ व्यापार करने की आवश्यकता होती है। वर्तमान स्थिति में मैं तर्क दूंगा कि आपको निवेश करने के लिए एक स्तर का घोंसला आपको ** का पालन करने की इजाजत देता है ** स्पष्ट रूप से स्पष्ट है **: जब आप 'साथ' देखते हैं, तो यह स्पष्ट है कि अंतिम हैंडलिंग होगी (बजाय तर्क के निष्पादन भाग्य के आधार पर)। "अंतर्निहित से स्पष्ट स्पष्ट है" पायथन सूची के जेन पर नंबर 2 है और इसलिए * अक्सर कम घोंसले को टंप करना चाहिए। सब ठीक हैं। –

7

ध्यान दें कि अजगर के ज़ेन भी कहते हैं:

सरल जटिल से बेहतर है।

जटिल जटिल से बेहतर है।

और

पठनीयता गिना जाता है।

  • सही व्यवहार के रूप में फ़ाइल हमेशा बंद कर दिया है
  • पठनीयता (with open(..) as f काफी समझा जा सकता है)

आप कर सकते हैं:

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

+0

आप जो कहते हैं वह बहुत ही सामान्य है ... आप "सही व्यवहार को लागू करने" बिंदु पर सही हैं, क्योंकि यह त्वरित हैकी कोड के लिए अच्छा होगा, लेकिन मैंने पाया कि वास्तव में वे लोग जो "त्वरित हैकी कोड" लिखते हैं कथन के साथ प्रयोग नहीं करते हैं। और पठनीयता भाग व्यक्तिपरक है (मुझे एक और इंडेंटेशन स्तर कम पठनीय लगता है, और जब आप फ़ाइल के रूप में "खुले (...) के साथ" एकाधिक फाइलें "जैसे करते हैं, तो फ़ाइल (3) के रूप में खोलें (...) खोलें (। ..) फ़ाइल 4 के रूप में: "यह बहुत अपठनीय हो जाता है क्योंकि आपको क्षैतिज या बदसूरत स्क्रॉल करना पड़ता है क्योंकि आप एकाधिक पंक्ति पर कथन के साथ विभाजित होते हैं। – NeuronQ

+0

क्या एक ही समय में चार फाइलें खोलने का कोई अच्छा कारण है? आमतौर पर मैं कर सकता हूं इनपुट फ़ाइलों से डेटा को क्रमशः और एक या अधिक आउटपुट फ़ाइलों को डेटा लिखने के लिए पढ़ें। हालांकि मैं कल्पना कर सकता हूं कि वहां ऐसी स्थितियां हों जहां चार फाइलों की आवश्यकता हो। –

+0

@NeuronQ: मैं कमांड को तोड़ने पर कुछ भी नहीं देख सकता अधिक लाइनें, विशेष रूप से जब 'ओपन (...) को एफएक्स' भागों के रूप में गठबंधन किया जाता है। मैं शिमोन से सहमत हूं कि यह सामान्य मामला नहीं है। वैसे भी, यह उसी तरह पठनीय है जैसे चार परिणाम' एफएक्स = ओपन (। ..) 'आदेशों का उपयोग किया गया था। – pepr

1
"Flat is better than nested" 

खैर, फ्लैट क्या है?

import thirdparty 
print "I Like Pie!" 

बनाम

import org.example.thirdparty.something 
System.out.println("I Like Cake") 

आदि ...

अजगर की जेन बस अपने कोड पर एक खरोज सीमा लागू नहीं है। यह आपको पठनीय (और इस प्रकार, बेहतर) कोड लिखने के लिए प्रोत्साहित करता है। यदि आपका with कथन एक फ़ंक्शन में है जो केवल वस्तुओं की 3 परतों (आदि, one.two.three.func()) द्वारा पहुंच योग्य है, तो यह एक समस्या है।

अन्यथा, तीन इंडेन्शन स्तर उतने ही अच्छे हैं जितना कोई भी।

1

कारण with पसंद करते हैं करने के लिए है कि आप मैन्युअल संबंधित संक्रिया जोड़ी की जरूरत नहीं है है (जैसे open(...)/.close(), लेकिन with निर्माण अधिक सामान्य है - न केवल फाइलों के साथ काम के लिए)। यह महत्वपूर्ण है अर्थात् उन मामलों में जब दूसरे ऑपरेशन को उन कारणों से निष्पादित नहीं किया जा सकता है जो स्रोत कोड से स्पष्ट रूप से दिखाई नहीं दे रहे हैं। आप मशीन को मेरे बारे में बता रहे हैं, और मशीन मानव के मामले में बेहतर है। इस तरह आप गंदे त्रुटियों के समूह से छुटकारा पा सकते हैं जिन्हें खोजना मुश्किल हो सकता है।

वैसे, आपको के बजाय open(...) का उपयोग करना चाहिए। पायथन 3 को file(...) के बारे में कुछ नहीं पता है और आपको अन्यथा बाद में अपना कोड ठीक करना होगा।

+0

दरअसल, शायद मुझे फ़ाइलों के मुकाबले अन्य चीज़ों के साथ 'साथ' के उपयोग का पता लगाना चाहिए, मैंने कभी भी यह एक अच्छा विचार नहीं दिया। हाँ, 'खुले (...)' मैं इसका उपयोग करता हूं, मुझे नहीं पता कि मेरा दिमाग कहाँ था जब मैंने 'फ़ाइल (...) लिखा था लेकिन सौभाग्य से यह सवाल के अर्थ को प्रभावित नहीं करता था। – NeuronQ

संबंधित मुद्दे