क्लासेस — डेटा और व्यवहार एक साथ
class, __init__ और self, मेथड्स, __repr__ से प्रिंट करने योग्य रूप, __eq__ से समानता, क्लास-लेवल बनाम इंस्टेंस-लेवल, और क्लास की आवश्यकता कब नहीं होती।
- 1समस्या
- 2समझें
- 3उदाहरण
- 4अनुमान
- 5स्वयं करें
- 6चुनौती
वह समस्या जिसे हम हल कर रहे हैं
अब तक हमने किसी एक चीज़ के कई गुणों को एक डिक्शनरी में रखा है।
order = {"name": "pen", "price": 15.0, "quantity": 3}
print(order["nmae"])KeyError: 'nmae'त्रुटि पकड़ी गई — लेकिन केवल तब जब वह पंक्ति चली।
और समस्या केवल वर्तनी (spelling) की नहीं है। डिक्शनरी में कोई भी की डाली जा सकती है, इसलिए कहीं भी यह नहीं लिखा है कि एक ऑर्डर लाइन में वास्तव में क्या होना चाहिए। इसका योग करने वाला फ़ंक्शन कहीं और है। डेटा एक जगह है, उसके साथ क्या किया जा सकता है वह दूसरी जगह है।
class OrderLine:
def __init__(self, name, price, quantity):
self.name = name
self.price = price
self.quantity = quantity
def total(self):
return round(self.price * self.quantity, 2)
line = OrderLine("pen", 15.0, 3)
print(line.name)
print(line.total())pen
45.0एक क्लास (Class) एक सांचा (mould) है: यह बताती है कि इस प्रकार की चीज़ में क्या है, और इसके साथ क्या किया जा सकता है।
इस मिशन के अंत तक आप सीखेंगे
- एक
classलिखना, और यह बताना कि__init__औरselfक्या करते हैं - मेथड्स (methods) लिखना
__repr__के साथ किसी ऑब्जेक्ट को प्रिंट करने योग्य रूप देना- क्लास एट्रिब्यूट और इंस्टेंस एट्रिब्यूट के बीच अंतर समझना
__eq__के साथ दो ऑब्जेक्ट्स को तुलनीय बनाना- यह बताना कि क्लास की आवश्यकता कब नहीं होती
पूर्वापेक्षाएँ: JSON और CSV.
self वास्तव में क्या है
self कोई जादुई शब्द नहीं है — यह पहला पैरामीटर है, और इसमें वह ऑब्जेक्ट आता है जिस पर मेथड को कॉल किया गया था।
line.total() लिखने का अर्थ है "OrderLine का total मेथड चलाएं, और इसे self के रूप में line दें"।
इसे भूल जाने पर संदेश पहली नज़र में अजीब लगता है:
class OrderLine:
def __init__(self, name):
self.name = name
def shout():
return "hello"
line = OrderLine("pen")
print(line.shout())TypeError: OrderLine.shout() takes 0 positional arguments but 1 was given"1 was given" — लेकिन कोष्ठक खाली थे! जो दिया गया वह स्वयं line ऑब्जेक्ट था, चुपचाप।
__init__ भी एक सामान्य मेथड है, एक विशेष नाम के साथ: ऑब्जेक्ट बनने के तुरंत बाद पायथन इसे कॉल करता है। इसके अंदर, self.name = name एट्रिब्यूट्स सेट करता है।
__repr__ — प्रिंट करने पर क्या दिखता है
__repr__ के बिना:
class OrderLine:
def __init__(self, name):
self.name = name
print(OrderLine("pen"))<__main__.OrderLine object at 0x00000213E88A9DF0>अंत में दी गई संख्या एक मेमोरी एड्रेस है। डिबगिंग करते समय यह किसी काम की नहीं होती।
__repr__ के साथ:
class OrderLine:
def __init__(self, name, price):
self.name = name
self.price = price
def __repr__(self):
return f"OrderLine(name={self.name!r}, price={self.price!r})"
line = OrderLine("pen", 15.0)
print(line)
print([line, line])OrderLine(name='pen', price=15.0)
[OrderLine(name='pen', price=15.0), OrderLine(name='pen', price=15.0)]दूसरी पंक्ति असली लाभ है: यह एक सूची के अंदर भी काम करती है।
समानता (__eq__) — डिफ़ॉल्ट वह नहीं है जो आप चाहते हैं
class OrderLine:
def __init__(self, name):
self.name = name
a = OrderLine("pen")
b = OrderLine("pen")
print(a == b)
print(a == a)False
Trueदोनों ऑब्जेक्ट्स में एक ही चीज़ है, फिर भी == असत्य (False) है। क्योंकि डिफ़ॉल्ट समानता पहचान (identity) है — == बिल्कुल is की तरह व्यवहार करता है।
इसे बदलना:
class OrderLine:
def __init__(self, name):
self.name = name
def __eq__(self, other):
return self.name == other.name
a = OrderLine("pen")
b = OrderLine("pen")
print(a == b)
print(a is b)True
Falseक्लास स्तर और इंस्टेंस स्तर
class Basket:
TAX_RATE = 0.15
items = []
def add(self, name):
self.items.append(name)
a = Basket()
b = Basket()
a.add("pen")
b.add("bag")
print(a.items)
print(b.items)
print(a.items is b.items)['pen', 'bag']
['pen', 'bag']
Trueदो अलग-अलग बास्केट, एक ही लिस्ट।
यह अध्याय 21 का म्युटेबल डिफ़ॉल्ट जाल है। class पंक्ति के ठीक नीचे items = [] केवल एक बार चलता है, जब क्लास बनाई जाती है। इसलिए सूची क्लास की होती है, और प्रत्येक इंस्टेंस इसे साझा करता है।
समाधान: जो कुछ भी प्रत्येक ऑब्जेक्ट का है, उसे __init__ के अंदर बनाएं।
class Basket:
TAX_RATE = 0.15
def __init__(self):
self.items = []
def add(self, name):
self.items.append(name)
a = Basket()
b = Basket()
a.add("pen")
b.add("bag")
print(a.items)
print(b.items)
print(a.TAX_RATE, b.TAX_RATE)['pen']
['bag']
0.15 0.15नियम: स्थिरांक (constants) क्लास स्तर पर; सब कुछ परिवर्तनशील (mutable) __init__ में।
एक संपूर्ण उदाहरण
"""दो छोटी कक्षाओं से बना एक ऑर्डर।"""
TAX_RATE = 0.15
class OrderLine:
"""ऑर्डर पर एक वस्तु: यह क्या है, इसकी कीमत क्या है, कितनी संख्या है।"""
def __init__(self, name, price, quantity):
if quantity < 1:
raise ValueError(f"quantity must be at least 1: {quantity}")
self.name = name
self.price = price
self.quantity = quantity
def total(self):
"""टैक्स सहित इस लाइन की कीमत।"""
return round(self.price * self.quantity * (1 + TAX_RATE), 2)
def __repr__(self):
return f"OrderLine({self.name!r}, {self.price!r}, {self.quantity!r})"
class Order:
"""लाइनों का एक संग्रह, और इसके बारे में पूछे जाने वाले प्रश्न।"""
def __init__(self, customer):
self.customer = customer
self.lines = []
def add(self, name, price, quantity):
self.lines.append(OrderLine(name, price, quantity))
return self
def total(self):
return round(sum(line.total() for line in self.lines), 2)
def largest(self):
"""सबसे महंगी लाइन, या खाली ऑर्डर के लिए None।"""
if not self.lines:
return None
return max(self.lines, key=lambda line: line.total())
def __repr__(self):
return f"Order({self.customer!r}, {len(self.lines)} lines)"
def main():
order = Order("rafi")
order.add("pen", 15.0, 3)
order.add("bag", 850.0, 1)
order.add("ink", 120.0, 2)
for line in order.lines:
print(f"{line.name:<6} {line.total():>9.2f}")
print(f"{'total':<6} {order.total():>9.2f}")
print()
print(order)
print("largest:", order.largest())
try:
order.add("clip", 5.0, 0)
except ValueError as err:
print("rejected:", err)
if __name__ == "__main__":
main()pen 51.75
bag 977.50
ink 276.00
total 1305.25
Order('rafi', 3 lines)
largest: OrderLine('bag', 850.0, 1)
rejected: quantity must be at least 1: 0चार बातें ध्यान देने योग्य हैं:
__init__ सत्यापन (validation) करता है। quantity < 1 के साथ ऑब्जेक्ट कभी बनता ही नहीं है।
Order यह नहीं जानता कि लाइन की कीमत कैसे तय होती है। यह बस line.total() को कॉल करता है।
दोनों कक्षाओं में __repr__ है।
जब यह टूटता है
TypeError: ... takes 0 positional arguments but 1 was given मेथड में self छूट गया है। इसे पहले पैरामीटर के रूप में दें।
AttributeError: 'X' object has no attribute 'y' वर्तनी की गलती, या self.y को __init__ में सेट नहीं किया गया था।
TypeError: X() takes no arguments कोई __init__ नहीं है, या नाम की वर्तनी गलत है (दोनों तरफ दो अंडरस्कोर)।
प्रत्येक ऑब्जेक्ट एक ही सूची साझा कर रहा है सूची क्लास स्तर पर रखी गई है। इसे __init__ के अंदर ले जाएं।
चरण 4 / 6 — अनुमान
अपनी समझ की जाँच करें
shout() is called with no arguments. What happens?
class OrderLine:
def __init__(self, name):
self.name = name
def shout():
return "hello"
line = OrderLine("pen")
print(line.shout())- AA `TypeError` — it takes zero, and one was given
- B`hello` prints
- CA `TypeError` — it takes one, and zero were given
- DAn `AttributeError`
Two separate baskets, one item each. What is printed?
class Basket:
items = []
def add(self, name):
self.items.append(name)
a = Basket()
b = Basket()
a.add("pen")
b.add("bag")
print(a.items)
print(b.items)- A['pen', 'bag'] ['pen', 'bag']
- B['pen'] ['bag']
- C['pen'] ['pen', 'bag']
- D['pen', 'bag'] []
The two objects hold the same name. What is printed?
class OrderLine:
def __init__(self, name):
self.name = name
a = OrderLine("pen")
b = OrderLine("pen")
print(a == b)
print(a == a)- AFalse True
- BTrue True
- CFalse False
- DA `TypeError`
उत्तर देने के लिए अकाउंट आवश्यक है
अपने उत्तर जाँचने के लिए साइन इन करें
प्रश्न ऊपर दिए गए हैं, और मन में उत्तर सोचना ही मुख्य कार्य है। सही उत्तर, व्याख्या और तीन-स्तरीय संकेत देखने के लिए साइन इन करें।
आपकी बारी
दो क्लासेस लिखें।
Book — title, author और pages से निर्मित। जब pages एक से कम हो तो यह ValueError उठाता है। इसे एक __repr__ दें, और एक __eq__ दें जो शीर्षक और लेखक मेल खाने पर दो पुस्तकों को समान माने।
Shelf — किताबें इकट्ठा करता है, और add(book), total_pages(), longest(), और by_author(name) प्रदान करता है।
Step 6 of 6
चुनौती — the chapter quiz
सरल से कठिन — दस प्रश्न, अंतिम वाले जानबूझकर चुनौतीपूर्ण बनाए गए हैं।
Sign in to take the quiz