Kodokon kodokon.com

OOP: क्लास, __init__, मेथड और इनहेरिटेंस

अच्छी तरह डिज़ाइन की गई क्लास से अपने कोड को व्यवस्थित करें: इनिशियलाइज़ेशन, इंस्टेंस या क्लास एट्रिब्यूट, इनहेरिटेंस और उसके समझौते।

10 मिनट · 3 प्रश्न

इस पाठ को Kodokon में खोलें

आप हर समय Python के ऑब्जेक्ट के साथ काम करते हैं: स्ट्रिंग, लिस्ट, फ़ाइलें। अपनी खुद की क्लास लिखने का मतलब है स्टेट (एट्रिब्यूट) और व्यवहार (मेथड) को एक सुसंगत इंटरफ़ेस के पीछे एक साथ बाँध देना। शब्दावली का एक ऐसा बिंदु जिसे अक्सर गलत समझा जाता है: __init__ कोई कंस्ट्रक्टर नहीं है। जब __init__ को self मिलता है, तब तक ऑब्जेक्ट पहले से मौजूद होता है (__new__ द्वारा बनाया गया); इसका काम इंस्टेंस को इनिशियलाइज़ करना है। और self में कुछ भी जादुई नहीं है: यह हर इंस्टेंस मेथड का पहला पैरामीटर है, जिसे Python कॉल के समय अपने आप पास कर देता है।

PYTHON
class Account:
    def __init__(self, owner, balance=0.0):
        self.owner = owner
        self.balance = balance

    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("amount must be > 0")
        self.balance += amount
        return self.balance

    def __repr__(self):
        return f"Account({self.owner!r}, {self.balance})"

account = Account("Ada")
account.deposit(120.0)
print(account)
एक संपूर्ण क्लास: __init__, एक बिज़नेस मेथड और __repr__

प्रोडक्शन में एक निर्णायक भेद: क्लास एट्रिब्यूट क्लास के मुख्य भाग में घोषित होते हैं और हर इंस्टेंस द्वारा साझा किए जाते हैं; इंस्टेंस एट्रिब्यूट self पर बनाए जाते हैं, आमतौर पर __init__ में। पढ़ते समय, Python पहले इंस्टेंस पर देखता है, फिर क्लास पर, फिर पैरेंट क्लास पर। असाइनमेंट self.x = ... हमेशा एक इंस्टेंस एट्रिब्यूट बनाता है, जो उसी नाम वाले क्लास एट्रिब्यूट को ढक देता है। वास्तविक दुनिया का क्लासिक जाल: एक म्यूटेबल क्लास एट्रिब्यूट।

PYTHON
class Basket:
    items = []

    def add(self, item):
        self.items.append(item)

a = Basket()
b = Basket()
a.add("apple")
print(b.items)  # ['apple']: shared list!
म्यूटेबल क्लास एट्रिब्यूट का जाल

इनहेरिटेंस एक "is a" (है एक) संबंध व्यक्त करता है: एक Car है एक Vehicle। सबक्लास मेथड इनहेरिट करती है, उन्हें ओवरराइड कर सकती है, और super() उसे पैरेंट वाला संस्करण कॉल करने देता है - __init__ में यह अनिवार्य है, ताकि आप पैरेंट का इनिशियलाइज़ेशन शॉर्ट-सर्किट न कर दें। Python MRO (Method Resolution Order) का अनुसरण करते हुए कॉल का समाधान करता है। हर बार इनहेरिटेंस की ओर मत भागिए: "is a" संबंध के बिना कोड का पुनः उपयोग करने के लिए, कंपोज़िशन को प्राथमिकता दें (एक ऑब्जेक्ट दूसरे का स्वामी होता है)। गहरी पदानुक्रम नाज़ुक होती हैं: हर पैरेंट क्लास अपनी सभी संतानों के लिए एक अंतर्निहित API बन जाती है।

PYTHON
class Vehicle:
    def __init__(self, brand):
        self.brand = brand

    def describe(self):
        return self.brand

class Car(Vehicle):
    def __init__(self, brand, doors):
        super().__init__(brand)
        self.doors = doors

    def describe(self):
        base = super().describe()
        return f"{base}, {self.doors} doors"

print(Car("Aster", 5).describe())
इनहेरिटेंस और super(): दोबारा लिखे बिना विस्तार करें

ज्ञान जांच

सुनिश्चित करें कि आपको इस पाठ के मुख्य बिंदु याद हैं।

  1. __init__ की भूमिका ठीक-ठीक क्या है?
    • मेमोरी में ऑब्जेक्ट बनाना
    • पहले से बनाए गए इंस्टेंस को इनिशियलाइज़ करना
    • क्लास एट्रिब्यूट घोषित करना
    • हर एट्रिब्यूट एक्सेस पर कॉल होना
  2. एक क्लास अपने मुख्य भाग में items = [] घोषित करती है। a.add(1) के बाद, जो self.items.append(1) चलाता है, दूसरा इंस्टेंस b क्या देखता है?
    • b.items एक खाली लिस्ट है
    • b.items में 1 है: लिस्ट साझा है
    • Python एक AttributeError फेंकता है
  3. Car.__init__ में, super().__init__(brand) कॉल का क्या मतलब है?
    • एक दूसरा Vehicle इंस्टेंस बनाना
    • पैरेंट क्लास में परिभाषित इनिशियलाइज़ेशन चलाना
    • Vehicle के मेथड को Car में कॉपी करना
    • यह जाँचना कि Car वाकई Vehicle से इनहेरिट करती है