कस्टम एक्सेप्शन

Python में, अपवाद (exceptions) उन त्रुटियों को संभालने का एक तरीका है जो प्रोग्राम के निष्पादन के दौरान उत्पन्न हो सकती हैं। Python में कई बिल्ट-इन अपवाद हैं, जैसे IndexError जब आप किसी सूची में मौजूद नहीं है ऐसे इंडेक्स को एक्सेस करने की कोशिश करते हैं, या TypeError जब आप किसी ऐसे प्रकार (type) पर ऑपरेशन करने की कोशिश करते हैं जो उसे समर्थन नहीं करता। लेकिन कभी-कभी, अपनी स्वयं की अपवादों को परिभाषित करना उपयोगी हो सकता है। इससे हम अर्थपूर्ण त्रुटि संदेश दे सकते हैं और ऐसी विशिष्ट स्थितियों पर प्रतिक्रिया कर सकते हैं जिन्हें बिल्ट-इन अपवाद संभाल नहीं सकते। कस्टम एक्सेप्शन बनाना सरल है; हम एक नया क्लास परिभाषित करते हैं जो बिल्ट-इन Exception क्लास या उसकी किसी उपकक्षा (subclass) से इनहेरिट करता है।
आइए एक प्रोग्राम पर विचार करें जो एक सैद्धांतिक पुस्तकालय प्रणाली के साथ काम करता है। इस प्रणाली में, किसी उपयोगकर्ता को एक बार में 5 से अधिक पुस्तकें चेक आउट करने की अनुमति नहीं होनी चाहिए। इसके लिए हम एक कस्टम अपवाद कैसे बना सकते हैं:
class TooManyBooksError(Exception):  # एक नया अपवाद क्लास परिभाषित करें
    pass

def checkout_books(user, num_books):
    if num_books > 5:  
        # यदि उपयोगकर्ता 5 से अधिक पुस्तकें चेक आउट करने की कोशिश करता है तो अपवाद उत्पन्न करें
        raise TooManyBooksError('You cannot check out more than 5 books at a time.')  # हमारा कस्टम अपवाद उठाएं
    # अन्यथा, पुस्तकों को उपयोगकर्ता के खाते में जोड़ दें।
    user.books += num_books
ऊपर के उदाहरण में, यदि कोई उपयोगकर्ता एक बार में 5 से अधिक पुस्तकें चेक आउट करने की कोशिश करता है, तो हमारा कस्टम TooManyBooksError एक विशिष्ट त्रुटि संदेश के साथ उठेगा। यदि अपवाद को पकड़ा नहीं जाता है, तो प्रोग्राम का निष्पादन रुक जाएगा, और त्रुटि संदेश कंसोल पर प्रिंट होगा।
हम इस अपवाद को बिल्ट-इन अपवादों की तरह ही try / except ब्लॉक का उपयोग करके पकड़ सकते हैं:
try:
    checkout_books(user, 7)     # 7 पुस्तकें चेक आउट करने की कोशिश करें।
except TooManyBooksError as e:  # हमारे कस्टम अपवाद को पकड़ें
    print(e)                    # त्रुटि संदेश प्रिंट करें।
यदि checkout_books(user, 7) लाइन एक TooManyBooksError उठाती है, तो प्रोग्राम इसे पकड़ लेगा और हमारा त्रुटि संदेश 'You cannot check out more than 5 books at a time.' प्रिंट करेगा। इस प्रकार, हम त्रुटि को सुगमतापूर्वक संभाल सकते हैं और प्रोग्राम चलता रहेगा।
किसी अन्य क्लास की तरह ही, हम अपने अपवाद क्लास में मेथड्स जोड़ सकते हैं। उदाहरण के लिए, आइए एक मेथड जोड़ते हैं जो गणना करता है कि उपयोगकर्ता को वांछित मात्रा में पुस्तकें चेक आउट करने के लिए कितनी पुस्तकें वापस करनी चाहिए:
class TooManyBooksError(Exception):  
    def __init__(self, attempted, limit=5, checked_out=0):  
        self.attempted = attempted
        self.limit = limit
        self.checked_out = checked_out
        self.message = f'You tried to check out {self.attempted} books, but the limit is {self.limit} books.'
        super().__init__(self.message)
    
    def books_to_return(self):
        return self.checked_out + self.attempted - self.limit
हम इस मेथड का उपयोग अपवाद को पकड़ने के बाद कर सकते हैं:
try:
    checkout_books(user, 7)
except TooManyBooksError as e:
    print(e)                                                   # आपने 7 पुस्तकें चेक आउट करने की कोशिश की, लेकिन सीमा 5 पुस्तकें है।
    print(f'You need to return {e.books_to_return()} books.')  # आपको 2 पुस्तकें वापस करनी हैं।
इस प्रकार, कस्टम अपवादों के अपने गुण और मेथड्स हो सकते हैं, जो उन्हें त्रुटियों को संभालने के लिए एक शक्तिशाली उपकरण बनाते हैं, विशेष रूप से आपके प्रोग्राम की विशेष आवश्यकताओं के लिए।
 

कस्टम अपवादों को परिभाषित करते समय सर्वोत्तम प्रथाएँ

जब आप कस्टम अपवाद बनाते हैं, तो अक्सर यह प्रलोभन होता है कि आप Exception से इनहेरिट करने वाला एक खाली क्लास परिभाषित करें, और फिर हर बार जब आप अपवाद उठाते हैं तो पूरे त्रुटि संदेश को एक स्ट्रिंग के रूप में पास करें। यह तरीका काम करता है, लेकिन इससे दोहरावदार कोड हो सकता है और आपके अपवाद संदेशों को सुसंगत रखना कठिन हो सकता है।
इसके बजाय, एक बेहतर तरीका यह है कि किसी भी गतिशील डेटा को अपवाद क्लास में संग्रहीत करें। इस तरह, आप अपवाद के संदेश को आंतरिक रूप से बना सकते हैं, जिससे आपका कोड अधिक स्वच्छ और संगठित हो जाएगा:
👎 खराब अभ्यास – हर बार पूरे संदेश को पास करना:
class TooManyBooksError(Exception):
    pass

# आपको हर बार संदेश पास करना पड़ता है
raise TooManyBooksError('You tried to check out 7 books, but the limit is 5!')

# लंबे समय में यह एक बुरा विचार है
👍 एक बेहतर तरीका – संबंधित विवरणों को अपवाद क्लास में पास करना:
class TooManyBooksError(Exception):
    def __init__(self, attempted, limit=5):
        self.attempted = attempted
        self.limit = limit
        # डेटा से त्रुटि संदेश बनाएं
        self.message = f'You tried to check out {self.attempted} books, but the limit is {self.limit}.'
        super().__init__(self.message)

# अपवाद उठाते समय, केवल संबंधित डेटा पास करें
raise TooManyBooksError(7)
💡
अपवाद क्लास को त्रुटि संदेश के निर्माण को संभालने देकर, आप स्वयं को दोहराते नहीं हैं। यदि आपको संदेश के शब्दों या स्वरूपण को बदलने की आवश्यकता है, तो आपको केवल एक ही जगह ऐसा करना होगा—अपने अपवाद के __init__ मेथड के अंदर।
 

चुनौती: आयु डेटाबेस

एक ऐसे शहर में जहाँ हर कोई एक-दूसरे को जानता है, स्थानीय सरकार बार, क्लब और थिएटर जैसे शहर के स्थलों पर आयु-जांच प्रणाली को लागू करने की कोशिश कर रही है। उन्हें एक प्रोग्राम की आवश्यकता है जो लोगों की आयु के एक शब्दकोश को देकर, एक नाम ले और उस व्यक्ति की आयु लौटाए।
इनपुट स्वतः संभाला जाता है। आपको find_age(name) फ़ंक्शन को लागू करना चाहिए जो एक नाम देकर उस व्यक्ति की आयु लौटाता है।
हालाँकि, सभी लोग शहर के डेटाबेस में नहीं हो सकते। यदि प्रोग्राम डेटाबेस में कोई नाम नहीं ढूँढ पाता है, तो उसे NameNotFoundError नामक कस्टम अपवाद उठाना चाहिए और एक उपयुक्त त्रुटि संदेश प्रिंट करना चाहिए: {name} not found in the database। सुनिश्चित करें कि संदेश को NameNotFoundError क्लास के भीतर बनाया गया हो।
इनपुट
आउटपुट
5 Alice - 24 Bob - 32 Charlie - 21 Daisy - 27 Edgar - 30 Edgar
Edgar - 30
5 Alice - 24 Bob - 32 Charlie - 21 Daisy - 27 Edgar - 30 George
NameNotFoundError: George not found in the database.
नोट: नाम और आयु केस-संवेदी हैं और उनमें रिक्त स्थान हो सकते हैं। दर्ज किया गया नाम डेटाबेस में मौजूद नाम से बिल्कुल मेल खाना चाहिए।
 

Constraints

Time limit: 2 seconds

Memory limit: 512 MB

Output limit: 1 MB

To check your solution you need to sign in
Sign in to continue