सवाल पाइथन 3 में किसी सूची के बजाय मानचित्र मानचित्र मानचित्र क्यों देता है?


मुझे समझने में दिलचस्पी है पायथन 3.x की नई भाषा डिजाइन

मैं पाइथन 2.7, समारोह में आनंद लेता हूं map:

Python 2.7.12
In[2]: map(lambda x: x+1, [1,2,3])
Out[2]: [2, 3, 4]

हालांकि, पायथन 3.x चीजों में बदल गया है:

Python 3.5.1
In[2]: map(lambda x: x+1, [1,2,3])
Out[2]: <map at 0x4218390>

मैं समझता हूं कि कैसे, लेकिन मुझे इसका संदर्भ क्यों नहीं मिला। भाषा डिजाइनरों ने यह विकल्प क्यों बनाया, जो मेरी राय में, दर्द का एक बड़ा सौदा पेश करता है। क्या यह सूची समझने के लिए चिपकने वाले हथियार-पहलवान डेवलपर्स के लिए था?

आईएमओ, सूची स्वाभाविक रूप से सोचा जा सकता है functors; और मुझे इस तरह से सोचने के लिए सोचा गया है:

fmap :: (a -> b) -> f a -> f b

52
2017-10-13 08:01


मूल


तर्क इस बात के समान होना चाहिए कि हम सूची समझ के बजाय जनरेटर का उपयोग क्यों करते हैं। आलसी मूल्यांकन का उपयोग करके हमें बड़ी चीजों को स्मृति में रखने की आवश्यकता नहीं है। यहां स्वीकृत उत्तर की जांच करें: stackoverflow.com/questions/1303347/... - Moberg
क्या आप समझा सकते हैं कि यह आपको "दर्द का एक बड़ा सौदा" क्यों लाता है? - RemcoGerlich
मुझे लगता है कि ऐसा इसलिए है क्योंकि उपयोग के वर्षों से पता चला है कि इसका सबसे आम उपयोग है map परिणाम पर बस पुनरावृत्त। जब आपको आवश्यकता नहीं होती है तो एक सूची बनाना अक्षम है इसलिए देवों ने निर्णय लेने का फैसला किया map आलसी। प्रदर्शन के लिए यहां बहुत कुछ हासिल किया जा सकता है और बहुत कुछ खोना नहीं है (यदि आपको एक सूची चाहिए, तो बस एक के लिए पूछें ... list(map(...)))। - mgilson
ठीक है, मुझे यह दिलचस्प लगता है कि फंक्टर पैटर्न को रखने और सूची के आलसी संस्करण की पेशकश करने के बजाय, किसी भी तरह से इसे मैप किए जाने पर सूची के आलसी मूल्यांकन को मजबूर करने का निर्णय लिया गया। मैं अपनी पसंद, उर्फ, जनरेटर -> मानचित्र -> जनरेटर या सूची -> मानचित्र -> सूची (निर्णय लेने के लिए मेरे ऊपर) बनाने का अधिकार पसंद करना चाहूंगा - NoIdeaHowToFixThis
@NoIdeaHowToFixThis, वास्तव में आप पर निर्भर है, अगर आपको पूरी सूची की आवश्यकता है, तो इसे नरक के रूप में आसान, एक सूची में बदलें - Netwave


जवाब:


मुझे लगता है कि नक्शा अभी भी क्यों मौजूद है बिलकुल कब जनरेटर अभिव्यक्तियां यह भी मौजूद है, यह है कि यह एकाधिक इटरेटर तर्क ले सकता है जो सभी लूप हो गए हैं और फ़ंक्शन में पास हो गए हैं:

>>> list(map(min, [1,2,3,4], [0,10,0,10]))
[0,2,0,4]

ज़िप का उपयोग करने से थोड़ा आसान है:

>>> list(min(x, y) for x, y in zip([1,2,3,4], [0,10,0,10]))

अन्यथा, यह जेनरेटर अभिव्यक्तियों पर कुछ भी नहीं जोड़ता है।


22
2017-10-13 08:17



मुझे लगता है कि अगर हम तनाव की इच्छा जोड़ते हैं कि सूची की समझ अधिक पाइथोनिक है और भाषा डिजाइनर उस पर दबाव डालना चाहते हैं, तो मुझे लगता है कि यह सबसे अधिक मौका जवाब है। @vishes_shell किसी भी तरह भाषा डिजाइन पर पर्याप्त ध्यान केंद्रित नहीं करता है। - NoIdeaHowToFixThis
पाइथन 2 और 3 में विभिन्न परिणाम उत्पन्न करता है यदि दो सूचियां बराबर लंबाई के नहीं हैं। प्रयत्न c = list(map(max, [1,2,3,4], [0,10,0,10, 99])) पायथन 2 और पायथन 3 में। - cdarke
यहां python3 से मानचित्र को हटाने के लिए मूल योजना का संदर्भ दिया गया है: artima.com/weblogs/viewpost.jsp?thread=98196 - TheEspinosa
हम्म, जब मैं सूची में मानचित्र लपेटता हूं तो मुझे कितना अजीब लगता है, मुझे 1 तत्व सूचियों की एक सूची मिलती है। - awiebe


चूंकि यह एक पुनरावर्तक लौटाता है, यह स्मृति में पूर्ण आकार की सूची को संग्रहीत करता है। ताकि भविष्य में आप इसे आसानी से फिर से शुरू कर सकें, स्मृति को कोई दर्द नहीं पहुंचाते। संभवतः आपको पूरी सूची की आवश्यकता नहीं है, लेकिन इसका हिस्सा तब तक है जब तक आपकी हालत पूरी नहीं हो जाती।

आप इसे पा सकते हैं डॉक्स उपयोगी, iterators भयानक हैं।

डेटा की एक धारा का प्रतिनिधित्व करने वाला एक वस्तु। इटेटरेटर को दोहराया गया कॉल __next__() विधि (या इसे अंतर्निहित फ़ंक्शन में पास कर रहा है next()) धारा में लगातार वस्तुओं को वापस। जब कोई और डेटा उपलब्ध नहीं होता है StopIteration इसके बजाय अपवाद उठाया जाता है। इस बिंदु पर, इटेटरेटर ऑब्जेक्ट समाप्त हो गया है और इसके लिए कोई और कॉल है __next__() विधि बस उठाओ StopIteration फिर। Iterators एक होना आवश्यक है __iter__() विधि जो इटेटरेटर ऑब्जेक्ट को स्वयं लौटाती है, इसलिए हर इटरेटर भी पुनरावर्तनीय होता है और अधिकांश स्थानों पर इसका उपयोग किया जा सकता है जहां अन्य पुनरावृत्तियों को स्वीकार किया जाता है। एक उल्लेखनीय अपवाद कोड है जो एकाधिक पुनरावृत्ति पास का प्रयास करता है। एक कंटेनर ऑब्जेक्ट (जैसे ए list) हर बार जब आप इसे पास करते हैं तो एक नया नया इटरेटर बनाता है iter() फंक्शन या लूप के लिए इसका इस्तेमाल करें। इसे एक पुनरावर्तक के साथ प्रयास करने से पिछले पुनरावृत्ति पास में उपयोग की जाने वाली एक ही थकाऊ इटरेटर ऑब्जेक्ट वापस आ जाएगा, जो इसे एक खाली कंटेनर की तरह दिखाई देता है।


16
2017-10-13 08:04





Guido इस सवाल का जवाब है यहाँ: "चूंकि एक सूची बनाना सिर्फ अपमानजनक होगा"।

वह यह भी कहता है कि सही परिवर्तन नियमित रूप से उपयोग करना है for पाश।

परिवर्तित map() 2 से 3 तक शायद चिपकाने का एक साधारण मामला न हो list( ) इसके आसपास। Guido भी कहते हैं:

"अगर इनपुट अनुक्रम बराबर लंबाई के नहीं हैं, map() अनुक्रमों के सबसे कम की समाप्ति पर रोक देंगे। के साथ पूर्ण संगतता के लिए map() पायथन 2.x से, अनुक्रमों को भी लपेटें itertools.zip_longest(), उदा।

map(func, *sequences)

हो जाता है

list(map(func, itertools.zip_longest(*sequences)))

"


10
2017-10-13 08:27



Guido टिप्पणी चालू है map() समारोह के दुष्प्रभावों के लिए आह्वान किया गया, एक मजेदार के रूप में इसके उपयोग पर नहीं। - abukaj
के साथ परिवर्तन zip_longest गलत है। आपको उपयोग करना है itertools.starmap इसके बराबर होना: list(starmap(func, zip_longest(*sequences)))। ऐसा इसलिए है क्योंकि zip_longest tuples पैदा करता है, तो func एक एकल प्राप्त होगा nके बजाय -अपूल तर्क nकॉल करते समय मामले के रूप में अलग तर्क map(func, *sequences)। - Bakuriu


पायथन 3 में कई फ़ंक्शन (न केवल map परंतु zip, range और अन्य) पूरी सूची के बजाय एक पुनरावर्तक लौटते हैं। आप एक इटरेटर (उदाहरण के लिए पूरी सूची को स्मृति में रखने से बचने के लिए) चाहते हैं या आप एक सूची चाहते हैं (उदा। इंडेक्स करने में सक्षम होने के लिए)।

हालांकि, मुझे लगता है कि पायथन 3 में बदलाव का मुख्य कारण यह है कि एक इटरेटर को एक सूची में बदलने के लिए यह छोटा है list(some_iterator) विपरीत समकक्ष iter(some_list) वांछित परिणाम प्राप्त नहीं करता है क्योंकि पूरी सूची पहले से ही बनाई गई है और स्मृति में आयोजित की गई है।

उदाहरण के लिए, पायथन 3 में list(range(n)) काम करने के लिए बहुत कम लागत के रूप में ठीक काम करता है range ऑब्जेक्ट और फिर इसे एक सूची में परिवर्तित कर रहा है। हालांकि, पायथन 2 में iter(range(n)) किसी भी स्मृति को सहेजता नहीं है क्योंकि पूरी सूची का निर्माण होता है range() इटरेटर बनने से पहले।

इसलिए, पायथन 2 में, सूची के बजाए एक इटरेटर बनाने के लिए अलग-अलग फ़ंक्शंस की आवश्यकता होती है, जैसे कि imap के लिये map (हालांकि वे हैं काफी समकक्ष नहीं है), xrange के लिये range, izip के लिये zip। इसके विपरीत पायथन 3 को केवल एक ही फ़ंक्शन की आवश्यकता होती है list() यदि आवश्यक हो तो कॉल पूरी सूची बनाता है।


8
2017-10-13 08:14



Python 2.7 कार्यों में AFAIK itertools इटेटर भी वापस करें। इसके अलावा, मैं iterators को आलसी सूचियों के रूप में नहीं देखूंगा, क्योंकि सूचियों को कई बार पुनरावृत्त किया जा सकता है और यादृच्छिक रूप से उपयोग किया जा सकता है। - abukaj
@abukaj ठीक है धन्यवाद, मैंने स्पष्ट होने की कोशिश करने के लिए अपना जवाब संपादित कर लिया है - Chris_Rands
मानचित्र एक इटरेटर कैसे ऑब्जेक्ट करता है? इसमें कोई अगला () विधि नहीं है ... - Igor Rivin
@IgorRivin आपका क्या मतलब है? पायथन 3 map वस्तुओं में एक है next() तरीका। पायथन 3 range रेंज ऑब्जेक्ट्स सख्ती से संकेतक नहीं हैं जिन्हें मैं जानता हूं - Chris_Rands
@ Anrisonda वितरण पायथन 3.6.2 में @Chris_Rands, कर रहा है foo = map(lambda x: x, [1, 2, 3]) एक नक्शा वस्तु देता है foo। करते हुए foo.next() एक त्रुटि के साथ वापस आता है: 'map' object has no attribute 'next' - Igor Rivin