ट्रैक
/
Python
Python
/
अभ्यास
/
हवाई जहाज़ के टिकट
हवाई जहाज़ के टिकट

हवाई जहाज़ के टिकट

सीखने का अभ्यास

परिचय

एक generator एक फंक्शन या एक्सप्रेशन है जो एक खास तरह का इटरेटर लौटाता है, जिसे generator iterator कहते हैं। Generator-iterator आलसी होते हैं: वे अपनी values मेमोरी में संग्रहीत नहीं करते, बल्कि ज़रूरत पड़ने पर उन्हें बनाते हैं।

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

जेनरेटर बनाना

जेनरेटर भी दूसरे लूप वाले या रिकर्सिव फंक्शन की तरह ही बनाए जाते हैं, लेकिन इनमें एक yield एक्सप्रेशन ज़रूरी होता है, जिसे हम थोड़ी देर बाद विस्तार से देखेंगे।

एक उदाहरण देखिए: एक फंक्शन जो संख्याओं के दिए गए ऐरे से उनके वर्ग लौटाता है। जैसा यह अभी लिखा है, इसमें पहले पूरा इनपुट प्रोसेस करना पड़ता है, तभी कोई वैल्यू लौटाई जा सकती है:

>>> def squares(list_of_numbers):
...     squares = []
...     for number in list_of_numbers:
...         squares.append(number ** 2)
...     return squares

आप उस फंक्शन को इस तरह जेनरेटर में बदल सकते हैं:

>>> def squares_generator(list_of_numbers):
...     for number in list_of_numbers:
...         yield number ** 2

इसके पीछे वजह यह है कि जेनरेटर तब काम आता है जब आपको सारी वैल्यू एक साथ नहीं चाहिए। इससे मेमोरी और प्रोसेसिंग पावर बचती है, क्योंकि सिर्फ उसी वैल्यू की गणना होती है जिस पर आप उसी समय काम कर रहे हैं।

जेनरेटर का उपयोग

Python में ज़्यादातर iterables की जगह जेनरेटर का इस्तेमाल किया जा सकता है। इसमें वे फंक्शन या ऑब्जेक्ट भी शामिल हैं जिन्हें आर्गुमेंट के तौर पर एक iterable/iterator चाहिए।

squares_generator() जेनरेटर का उपयोग करने के लिए:

>>> squared_numbers = squares_generator([1, 2, 3, 4])

>>> for square in squared_numbers:
...     print(square)
...
1
4
9
16

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

>>> squared_numbers = squares_generator([1, 2])

>>> next(squared_numbers)
1
>>> next(squared_numbers)
4

जब किसी generator-iterator की सारी वैल्यू खत्म हो जाती हैं और लौटाने के लिए कुछ बचता नहीं, तो वह StopIteration एरर फेंकता है।

>>> next(squared_numbers)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
Note

जेनरेटर-इटरेटर इटरेटर का एक खास उपसमूह हैं। Iterators वह तंत्र या प्रोटोकॉल हैं जो iterables पर लूप चलाना संभव बनाते हैं। जेनरेटर-इटरेटर और Python के आम iterables से मिलने वाले इटरेटर लगभग एक जैसा व्यवहार करते हैं, लेकिन इनमें कुछ ज़रूरी अंतर ध्यान देने योग्य हैं:

  • वे आलसी तरीके से मूल्यांकित होते हैं; इटरेशन एकतरफा होता है और किसी पिछली वैल्यू पर "वापस जाने" का कोई रास्ता नहीं है।
  • लौटाई गई वैल्यू पर इटरेशन करने से वे खर्च हो जाते हैं; मेमोरी में कोई रीसेट या सेव नहीं होता।
  • इन्हें क्रम में नहीं लगाया जा सकता और न ही उलटा किया जा सकता है।
  • ये सीक्वेंस टाइप नहीं हैं, और इनमें indexes नहीं होते। आप जोड़ या घटाव के ज़रिये किसी पिछली या आगे की वैल्यू को नहीं पा सकते, और न ही ब्रैकेट ([]) संकेतन या स्लाइसिंग का इस्तेमाल कर सकते हैं।
  • इन्हें len() फंक्शन के साथ इस्तेमाल नहीं किया जा सकता, क्योंकि इनकी कोई लंबाई नहीं होती।
  • ये सीमित या असीमित हो सकते हैं। एक असीमित generator-iterator से सारी वैल्यू जमा करते समय सावधान रहिए!

yield एक्सप्रेशन

yield एक्सप्रेशन yield expression बहुत कुछ return एक्सप्रेशन जैसा होता है। return एक्सप्रेशन से अलग, yield कॉलर को वैल्यू एक खास बिंदु पर सौंप देता है, और तब तक कोई अतिरिक्त वैल्यू नहीं लौटाता जब तक उनकी माँग न की जाए। जब yield का मूल्यांकन होता है, तो यह अपने फंक्शन का निष्पादन रोक देता है और उस समय फंक्शन की जो भी वैल्यू हैं, उन्हें लौटा देता है। इसके बाद फंक्शन स्कोप में बना रहता है, और जब __next__() कॉल होता है, तो निष्पादन तब तक आगे बढ़ता है जब तक yield दोबारा न मिल जाए।

Note

फंक्शन के बाहर yield एक्सप्रेशन का इस्तेमाल करना मना है।

>>> def infinite_sequence():
...     current_number = 0
...     while True:
...         yield current_number
...         current_number += 1

>>> lets_try = infinite_sequence()
>>> lets_try.__next__()
0
>>> lets_try.__next__()
1

जेनरेटर क्यों बनाना चाहिए?

जेनरेटर कई जगहों पर काम आते हैं।

जब बहुत बड़ी संख्या में वैल्यू के साथ काम करना हो, तो आप शायद उन सबको मेमोरी में न रखना चाहें। ऐसे में जेनरेटर की मदद से बड़े डेटा पर टुकड़े-टुकड़े करके काम किया जा सकता है, जिससे मेमोरी बचती है और परफॉर्मेंस सुधरती है।

जेनरेटर तब भी बहुत काम आते हैं जब कोई प्रक्रिया या गणना जटिल, खर्चीली, या असीमित हो:

>>> def infinite_sequence():
...     current_number = 0
...     while True:
...         yield current_number
...         current_number += 1

अब जब भी infinite_sequence ऑब्जेक्ट पर __next__() कॉल होता है, यह पिछली संख्या + 1 लौटाता है।

निर्देश

Conda Airlines प्रोग्रामिंग की दुनिया की सबसे बड़ी एयरलाइन है, जिसकी रोज़ाना 10,000 से ज़्यादा उड़ानें हैं!

फिलहाल यह सभी सीटें यात्रियों को हाथ से असाइन करती है; इसे स्वचालित करना होगा।

उन्होंने आपसे यात्रियों की सीट असाइन करने की प्रक्रिया स्वचालित करने वाला सॉफ्टवेयर बनाने के लिए कहा है। उनकी माँग है कि आपका सॉफ्टवेयर मेमोरी की दृष्टि से कुशल हो और अच्छा प्रदर्शन दे।

1. सीट अक्षर बनाइए

Conda अपने विमानों के लिए सीट अक्षर बनाना चाहता है। एक विमान सीटों की कई पंक्तियों से बना होता है। हर पंक्ति में 4 सीटें होती हैं। हर पंक्ति की सीटों के नाम हमेशा A, B, C और D होते हैं। पंक्ति की पहली सीट A होती है, दूसरी सीट B, और इसी तरह आगे। D तक पहुँचने के बाद फिर A से शुरू होना चाहिए।

एक फंक्शन generate_seat_letters(<number>) बनाइए जो एक int लेता है, जिसमें यह रहता है कि कितने सीट अक्षर बनाने हैं। इसके बाद फंक्शन को सीट अक्षरों का एक इटरेबल लौटाना चाहिए।

>>> letters = generate_seat_letters(4)
>>> next(letters)
"A"
>>> next(letters)
"B"

2. सीटें बनाइए

Conda चाहता है कि एक ऐसा सिस्टम हो जो उसके विमानों के लिए तय संख्या में सीटें बना सके। हर विमान की हर पंक्ति में 4 सीटें होती हैं। पंक्तियों को संख्याओं से पहचाना जाता है, जो 1 से शुरू होकर आगे बढ़ती हैं। सीटें इस क्रम में होनी चाहिए, जैसे: 1A, 1B, 1C, 1D, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, ...

यहाँ एक उदाहरण है:

x 1 2
पंक्ति 5 21
सीट अक्षर A D
परिणाम 5A 21D

यात्रियों के अंधविश्वास के कारण कई एयरलाइनों की उड़ानों में पंक्ति संख्या 13 नहीं होती। Conda Airlines भी इसी परंपरा का पालन करता है, इसलिए ध्यान रखिए कि आप पंक्ति संख्या 13 के लिए सीटें न बनाएँ।

एक फंक्शन generate_seats(<number>) बनाइए जो एक int लेता है, जिसमें यह रहता है कि कितनी सीटें बनानी हैं। इसके बाद फंक्शन को उन सीटों का एक इटरेबल लौटाना चाहिए।

>>> seats = generate_seats(10)
>>> next(seats)
"1A"
>>> next(seats)
"1B"

3. यात्रियों को सीट असाइन कीजिए

अब जब आपके पास सीटें बनाने वाला फंक्शन है, तो आप इसकी मदद से यात्रियों को सीट असाइन कर सकते हैं।

एक फंक्शन assign_seats(<passengers>) बनाइए जो यात्रियों के नामों की एक list लेता है। इसके बाद फंक्शन को एक डिक्शनरी लौटानी चाहिए, जिसमें passenger की हो और seat_number वैल्यू।

>>> passengers = ['Jerimiah', 'Eric', 'Bethany', 'Byte', 'SqueekyBoots', 'Bob']

>>> assign_seats(passengers)
{'Jerimiah': '1A', 'Eric': '1B', 'Bethany': '1C', 'Byte': '1D', 'SqueekyBoots': '2A', 'Bob': '2B'}

4. टिकट कोड

Conda Airlines चाहता है कि हर टिकट के लिए एक अनोखा कोड हो। चूँकि यह एक बड़ी एयरलाइन है, इसकी बहुत सारी उड़ानें हैं। इसका मतलब है कि एक ही सीट संख्या वाली कई उड़ानें होती हैं। वे चाहते हैं कि आप एक ऐसा सिस्टम बनाइए जो एक अनोखा टिकट तैयार करे, जो 12 अक्षरों की स्ट्रिंग हो।

यह कोड assigned_seat से शुरू होता है और उसके बाद flight_id आता है। कोड का बाकी हिस्सा 0s से भर दिया जाता है।

एक फंक्शन generate_codes(<seat_numbers>, <flight_id>) बनाइए जो seat_numbers की एक list और उड़ान संख्या वाली एक string लेता है। इसके बाद फंक्शन को एक generator लौटाना चाहिए जो ticket_number देता है।

>>> seat_numbers = ['1A', '17D']
>>> flight_id = 'CO1234'
>>> ticket_ids = generate_codes(seat_numbers, flight_id)

>>> next(ticket_ids)
'1ACO12340000'
>>> next(ticket_ids)
'17DCO1234000'
GitHub के ज़रिए संपादित करें यह लिंक एक नई विंडो या टैब में खुलता है
Python Exercism

हवाई जहाज़ के टिकट शुरू करने के लिए तैयार हैं?

Exercism पर साइन अप कीजिए और Python को 17 कॉन्सेप्ट146 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।