मुख्य सामग्री पर जाएँ

Python डेटा क्लासेस: एक व्यापक ट्यूटोरियल

Python डेटा क्लासेस पर शुरुआती-अनुकूल ट्यूटोरियल और इन्हें व्यवहार में कैसे इस्तेमाल करें
· 9 मि॰ पढ़ें

AI के साथ खोजें

डेटा क्लासेस Python की उन विशेषताओं में से हैं जिन्हें एक बार समझ लेने के बाद आप पुराने तरीके पर वापस नहीं जाते। इस सामान्य क्लास पर विचार करें:

class Exercise:
   def __init__(self, name, reps, sets, weight):
       self.name = name
       self.reps = reps
       self.sets = sets
       self.weight = weight

मेरे लिए, यह क्लास डेफिनिशन काफी अल्प-कार्यकुशल है — __init__ मेथड में, आप हर पैरामीटर को कम-से-कम तीन बार दोहराते हैं। यह सुनने में बड़ी बात न लगे, लेकिन सोचिए, अपने करियर में आप कितनी बार अधिक पैरामीटर वाली क्लासेस लिखते हैं।

तुलना के लिए, ऊपर दिए गए कोड का डेटा क्लासेस विकल्प देखें:

from dataclasses import dataclass


@dataclass
class Exercise:
   name: str
   reps: int
   sets: int
   weight: float  # Weight in lbs

यह सादा-सा दिखने वाला कोड एक सामान्य क्लास से कई गुना बेहतर है। छोटा-सा @dataclass डेकोरेटर पर्दे के पीछे __init__, __repr__, __eq__ जैसी क्लासेस (मेथड) बना देता है, जिनके लिए हाथ से कम-से-कम 20 पंक्तियों का कोड लिखना पड़ता।

इसके अलावा, कई अन्य सुविधाएँ जैसे तुलना ऑपरेटर, ऑब्जेक्ट ऑर्डरिंग और इम्यूटेबिलिटी, हमारी क्लास के लिए एक ही पंक्ति में जादुई रूप से सक्षम की जा सकती हैं।

तो, इस ट्यूटोरियल का उद्देश्य आपको दिखाना है कि यदि आप ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग पसंद करते हैं, तो डेटा क्लासेस Python के लिए हुई सबसे अच्छी चीजों में से क्यों हैं।

चलिए शुरू करते हैं!

Python डेटा क्लासेस की बुनियाद

आइए Python डेटा क्लासेस की कुछ मूलभूत अवधारणाएँ कवर करें जो इन्हें इतना उपयोगी बनाती हैं।

डेटा क्लासेस में कुछ मेथड अपने-आप जनरेट हो जाते हैं

अपनी सभी खूबियों के बावजूद, डेटा क्लासेस सामान्य क्लासेस ही हैं जिनसे वही कार्यक्षमता बहुत कम कोड में मिल जाती है। यहाँ Exercise क्लास फिर से देखें:

from dataclasses import dataclass


@dataclass
class Exercise:
   name: str
   reps: int
   sets: int
   weight: float


ex1 = Exercise("Bench press", 10, 3, 52.5)

# Verifying Exercise is a regular class
ex1.name
'Bench press'

इस समय, Exercise में पहले से ही __repr__ और __eq__ मेथड इम्प्लीमेंटेड हैं। आइए जाँचते हैं:

repr(ex1)
"Exercise(name='Bench press', reps=10, sets=3, weight=52.5)"

किसी ऑब्जेक्ट का प्रतिनिधित्व repr ऐसा कोड लौटाना चाहिए जो स्वयं को पुनः बना सके, और हम देख सकते हैं कि ex1 के लिए बिल्कुल यही हो रहा है।

इसके विपरीत, पुराने तरीके से परिभाषित Exercise ऐसा दिखेगा:

class Exercise:
   def __init__(self, name, reps, sets, weight):
       self.name = name
       self.reps = reps
       self.sets = sets
       self.weight = weight


ex3 = Exercise("Bench press", 10, 3, 52.5)

ex3
<__main__.Exercise at 0x7f6834100130>

काफी बेडौल और बेकार-सा लगता है!

अब, आइए __eq__ यानी इक्वैलिटी ऑपरेटर की मौजूदगी जाँचें:

# Redefine the class
@dataclass
class Exercise:
   name: str
   reps: int
   sets: int
   weight: float


ex1 = Exercise("Bench press", 10, 3, 52.5)
ex2 = Exercise("Bench press", 10, 3, 52.5)

क्लास को अपने ही समान और समान पैरामीटर वाली दूसरी क्लास से तुलना करने पर True आना चाहिए:

ex1 == ex2
True
ex1 == ex1
True

और वैसा ही होता है! सामान्य क्लासेस में यह लॉजिक लिखना झंझटभरा होता।

डेटा क्लासेस में टाइप हिंट जरूरी हैं

जैसा कि आपने देखा होगा, फील्ड्स परिभाषित करते समय डेटा क्लासेस में टाइप हिंट जरूरी होते हैं। दरअसल, डेटा क्लासेस typing मॉड्यूल के किसी भी टाइप की अनुमति देती हैं। उदाहरण के लिए, ऐसा फील्ड कैसे बनाएँ जो Any डेटा टाइप स्वीकार कर सके:

from typing import Any


@dataclass
class Dummy:
   attr: Any

हालाँकि, Python की विशेषता यह है कि भले ही डेटा क्लासेस टाइप हिंट माँगती हैं, टाइप वास्तव में लागू नहीं कराए जाते।

उदाहरण के लिए, Exercise क्लास का ऐसा इंस्टेंस बनाना जिसमें पूरी तरह गलत डेटा टाइप हों, बिना एरर के चल जाएगा:

silly_exercise = Exercise("Bench press", "ten", "three sets", 52.5)

silly_exercise.sets

“Three sets”

यदि आप डेटा टाइप लागू कराना चाहते हैं, तो आपको Mypy जैसे टाइप चेकर का उपयोग करना होगा।

डेटा क्लासेस फील्ड्स में डिफॉल्ट वैल्यू स्वीकार करती हैं

अब तक, हमने अपनी क्लासेस में कोई डिफॉल्ट नहीं जोड़ा है। आइए इसे ठीक करें:

@dataclass
class Exercise:
   name: str = "Push-ups"
   reps: int = 10
   sets: int = 3
   weight: float = 0


# Now, all fields have defaults
ex5 = Exercise()
ex5
Exercise(name='Push-ups', reps=10, sets=3, weight=0)

ध्यान रखें कि नॉन-डिफॉल्ट फील्ड्स, डिफॉल्ट फील्ड्स के बाद नहीं आ सकतीं। उदाहरण के लिए, नीचे का कोड एरर देगा:

@dataclass
class Exercise:
   name: str = "Push-ups"
   reps: int = 10
   sets: int = 3
   weight: float  # NOT ALLOWED


ex5 = Exercise()
ex5
TypeError: non-default argument 'weight' follows default argument

व्यवहार में, आप शायद ही कभी name: type = value सिंटैक्स से डिफॉल्ट्स तय करेंगे।

इसके बजाय, आप field फ़ंक्शन का उपयोग करेंगे, जो हर फील्ड की परिभाषा पर अधिक नियंत्रण देता है:

from dataclasses import field


@dataclass
class Exercise:
   name: str = field(default="Push-up")
   reps: int = field(default=10)
   sets: int = field(default=3)
   weight: float = field(default=0)


# Now, all fields have defaults
ex5 = Exercise()
ex5
Exercise(name='Push-up', reps=10, sets=3, weight=0)

field फ़ंक्शन के और भी पैरामीटर हैं, जैसे:

  • repr
  • init
  • compare
  • default_factory

आदि। हम इन्हें आगे की धाराओं में चर्चा करेंगे।

डेटा क्लासेस एक फ़ंक्शन से भी बनाई जा सकती हैं

डेटा क्लासेस की बुनियाद पर एक अंतिम टिप्पणी यह है कि make_dataclass फ़ंक्शन का उपयोग करके इनकी परिभाषा और भी छोटी हो सकती है:

from dataclasses import make_dataclass

Exercise = make_dataclass(
   "Exercise",
   [
       ("name", str),
       ("reps", int),
       ("sets", int),
       ("weight", float),
   ],
)

ex3 = Exercise("Deadlifts", 8, 3, 69.0)
ex3
Exercise(name='Deadlifts', reps=8, sets=3, weight=69.0)

लेकिन आप पठनीयता का त्याग करेंगे, इसलिए मैं इस फ़ंक्शन का उपयोग करने की सलाह नहीं देता।

एडवांस्ड Python डेटा क्लासेस

इस खंड में, हम डेटा क्लासेस की उन्नत सुविधाओं पर चर्चा करेंगे जो और लाभ देती हैं। ऐसी ही एक सुविधा है डिफॉल्ट फ़ैक्टरी।

डिफॉल्ट फ़ैक्टरीज़

डिफॉल्ट फ़ैक्टरी समझाने के लिए, WorkoutSession नाम की एक और क्लास बनाते हैं जो दो फील्ड स्वीकार करती है:

from dataclasses import dataclass
from typing import List


@dataclass
class Exercise:
   name: str = "Push-ups"
   reps: int = 10
   sets: int = 3
   weight: float = 0


@dataclass
class WorkoutSession:
   exercises: List[Exercise]
   duration_minutes: int

List टाइप का उपयोग करके, हम यह निर्दिष्ट कर रहे हैं कि WorkoutSession Exercise इंस्टेंसेज़ की एक सूची स्वीकार करता है।

# Define the Exercise instances for HIIT training
ex1 = Exercise(name="Burpees", reps=15, sets=3)
ex2 = Exercise(name="Mountain Climbers", reps=20, sets=3)
ex3 = Exercise(name="Jump Squats", reps=12, sets=3)
exercises_monday = [ex1, ex2, ex3]

hiit_monday = WorkoutSession(exercises=exercises_monday, duration_minutes=30)

अभी, हर वर्कआउट सेशन इंस्टेंस को इनिशियलाइज़ करते समय एक्सरसाइज़ देनी पड़ती हैं। लेकिन लोग ऐसे वर्कआउट नहीं करते — पहले वे सेशन शुरू करते हैं (शायद किसी ऐप में), और फिर करते-करते एक्सरसाइज़ जोड़ते हैं।

इसलिए, हमें बिना एक्सरसाइज़ और बिना ड्यूरेशन के सेशन बना सकने चाहिए। आइए exercises के लिए खाली सूची को डिफॉल्ट वैल्यू के रूप में जोड़कर यह करें:

@dataclass
class WorkoutSession:
   exercises: List[Exercise] = []
   duration_minutes: int = None


hiit_monday = WorkoutSession("25-02-2024")
ValueError: mutable default <class 'list'> for field exercises is not allowed: use default_factory

लेकिन हमें एरर मिला — दरअसल, डेटा क्लासेस म्यूटेबल डिफॉल्ट वैल्यू की अनुमति नहीं देतीं।

सौभाग्य से, हम इसे डिफॉल्ट फ़ैक्टरी का उपयोग करके ठीक कर सकते हैं:

@dataclass
class WorkoutSession:
   exercises: List[Exercise] = field(default_factory=list)  # PAY ATTENTION
   duration_minutes: int = 0


hiit_monday = WorkoutSession()
hiit_monday
WorkoutSession(exercises=[], duration_minutes=0)

default_factory पैरामीटर किसी फ़ंक्शन को स्वीकार करता है जो डेटा क्लास फील्ड के लिए आरंभिक मान लौटाता है। यानी यह कोई भी मनचाहा फ़ंक्शन स्वीकार कर सकता है:

  • tuple
  • dict
  • set
  • कोई भी यूज़र-डिफाइंड कस्टम फ़ंक्शन

यह बात इस पर निर्भर नहीं करती कि फ़ंक्शन का परिणाम म्यूटेबल है या नहीं।

अब, सोचें तो अधिकतर लोग अपने प्रशिक्षण की शुरुआत वार्म-अप एक्सरसाइज़ से करते हैं, जो लगभग हर तरह के वर्कआउट के लिए मिलती-जुलती होती हैं। इसलिए, बिना एक्सरसाइज़ के सेशन इनिशियलाइज़ करना कुछ लोगों को नहीं भा सकता।

इसके बजाय, एक फ़ंक्शन बनाते हैं जो तीन वार्म-अप Exercises लौटाए:

def create_warmup():
   return [
       Exercise("Jumping jacks", 30, 1),
       Exercise("Squat lunges", 10, 2),
       Exercise("High jumps", 20, 1),
   ]

@dataclass
class WorkoutSession:
   exercises: List[Exercise] = field(default_factory=create_warmup)
   duration_minutes: int = 5  # Increase the default duration as well


hiit_monday = WorkoutSession()
hiit_monday

WorkoutSession(exercises=[Exercise(name='Jumping jacks', reps=30, sets=1, weight=0), Exercise(name='Squat lunges', reps=10, sets=2, weight=0), Exercise(name='High jumps', reps=20, sets=1, weight=0)], duration_minutes=5)

अब, जब भी हम कोई सेशन बनाएँगे, वे कुछ वार्म-अप एक्सरसाइज़ के साथ पहले से लॉग होकर आएँगे। WorkoutSession का नया संस्करण इस बात के लिए डिफॉल्ट ड्यूरेशन पाँच मिनट रखता है।

डेटा क्लासेस में मेथड जोड़ना

क्योंकि डेटा क्लासेस सामान्य क्लासेस ही हैं, इनमें मेथड जोड़ना भी वही रहता है। अपनी WorkoutSession डेटा क्लास में दो मेथड जोड़ते हैं:

@dataclass
class WorkoutSession:
   exercises: List[Exercise] = field(default_factory=create_warmup)
   duration_minutes: int = 5

   def add_exercise(self, exercise: Exercise):
       self.exercises.append(exercise)

   def increase_duration(self, minutes: int):
       self.duration_minutes += minutes

इन मेथड्स से अब हम किसी भी नई गतिविधि को सेशन में लॉग कर सकते हैं:

hiit_monday = WorkoutSession()

# Log a new exercise
new_exercise = Exercise("Deadlifts", 6, 4, 60)

hiit_monday.add_exercise(new_exercise)
hiit_monday.increase_duration(15)

लेकिन एक समस्या है:

hiit_monday

WorkoutSession(exercises=[Exercise(name='Jumping jacks', reps=30, sets=1, weight=0), Exercise(name='Squat lunges', reps=10, sets=2, weight=0), Exercise(name='High jumps', reps=20, sets=1, weight=0), Exercise(name='Deadlifts', reps=6, sets=4, weight=60)], duration_minutes=20)

सेशन को प्रिंट करने पर इसकी डिफॉल्ट रेप्रेज़ेंटेशन बहुत लंबी और अपठनीय है, क्योंकि इसमें ऑब्जेक्ट को पुनः बनाने वाला कोड आता है। आइए इसे ठीक करें।

__repr__ और __str__ डेटा क्लासेस में

डेटा क्लासेस __repr__ ऑटोमेटिकली इम्प्लीमेंट करती हैं, लेकिन __str__ नहीं। इसलिए print कॉल करने पर क्लास __repr__ पर लौट आती है।

तो, __str__ को स्वयं परिभाषित करके इस व्यवहार को ओवरराइड करते हैं:

@dataclass
class Exercise:
   name: str = "Push-ups"
   reps: int = 10
   sets: int = 3
   weight: float = 0

   def __str__(self):
       base = f"{self.name}: {self.reps}/{self.sets}"
       if self.weight == 0:
           return base
       return base + f", {self.weight} lbs"


ex1 = Exercise(name="Burpees", reps=15, sets=3)
ex1
Exercise(name='Burpees', reps=15, sets=3, weight=0)

__repr__ वही बना रहता है, लेकिन print कॉल करने पर:

print(ex1)
Burpees: 15/3

क्लास की स्ट्रिंग रेप्रेज़ेंटेशन कहीं बेहतर है। अब, WorkoutSession भी ठीक करते हैं:

@dataclass
class WorkoutSession:
   exercises: List[Exercise] = field(default_factory=create_warmup)
   duration_minutes: int = 5  # Increase the default duration as well

   def add_exercise(self, exercise: Exercise):
       self.exercises.append(exercise)

   def increase_duration(self, minutes: int):
       self.duration_minutes += minutes

   def __str__(self):
       base = ""

       for ex in self.exercises:
           base += str(ex) + "\n"
       base += f"\nSession duration: {self.duration_minutes} minutes."

       return base


hiit_monday = WorkoutSession()
print(hiit_monday)

Jumping jacks: 30/1
Squat lunges: 10/2
High jumps: 20/1

Session duration: 5 minutes.

ध्यान दें: कोड की पंक्ति-दर-पंक्ति व्याख्या के लिए स्निपेट के नीचे दिए “Explain code” बटन का उपयोग करें।

अब हमारे पास पठनीय और सुस्पष्ट आउटपुट है।

डेटा क्लासेस में तुलना

कई क्लासेस के लिए, उनके ऑब्जेक्ट्स की कुछ लॉजिक से तुलना करना समझदारी होती है। वर्कआउट के लिए, यह ड्यूरेशन, एक्सरसाइज़ की तीव्रता या वेट हो सकता है।

पहले देखते हैं कि मौजूदा स्थिति में दो वर्कआउट की तुलना करने पर क्या होता है:

hiit_wednesday = WorkoutSession()

hiit_wednesday.add_exercise(Exercise("Pull-ups", 7, 3))
print(hiit_wednesday)

Jumping jacks: 30/1
Squat lunges: 10/2
High jumps: 20/1
Pull-ups: 7/3

Session duration: 5 minutes.

hiit_monday > hiit_wednesday
TypeError: '>' not supported between instances of 'WorkoutSession' and 'WorkoutSession'

हमें TypeError मिलता है क्योंकि डेटा क्लासेस तुलना ऑपरेटर इम्प्लीमेंट नहीं करतीं। लेकिन इसे order पैरामीटर True कर के आसानी से ठीक किया जा सकता है:

@dataclass(order=True)
class WorkoutSession:
   exercises: List[Exercise] = field(default_factory=create_warmup)
   duration_minutes: int = 5

   ...

hiit_monday = WorkoutSession()
# hiit_monday.add_exercise(...)
hiit_monday.increase_duration(10)

hiit_wednesday = WorkoutSession()

hiit_monday > hiit_wednesday

True

इस बार तुलना काम करती है, लेकिन हम तुलना किस आधार पर कर रहे हैं?

डेटा क्लासेस में तुलना फील्ड्स के परिभाषित क्रम में होती है। अभी, तुलना वर्कआउट ड्यूरेशन के आधार पर हो रही है क्योंकि पहला फील्ड exercises नॉन-स्टैंडर्ड ऑब्जेक्ट्स रखता है।

हम इसे बुधवार वाले सेशन की ड्यूरेशन बढ़ाकर जाँच सकते हैं:

hiit_monday = WorkoutSession()
# hiit_monday.add_exercise(...)

hiit_wednesday = WorkoutSession()
hiit_wednesday.increase_duration(10)

hiit_monday > hiit_wednesday
False

अपेक्षित रूप से, हमें False मिला।

लेकिन क्या होगा अगर Workout का पहला फील्ड किसी और प्रकार का हो, जैसे कि स्ट्रिंग? आज़माते हैं:

@dataclass(order=True)
class WorkoutSession:
   date: str = None  # DD-MM-YYYY
   exercises: List[Exercise] = field(default_factory=create_warmup)
   duration_minutes: int = 5

   ...

hiit_monday = WorkoutSession("25-02-2024")
hiit_monday.increase_duration(10)

hiit_wednesday = WorkoutSession("27-02-2024")

hiit_monday > hiit_wednesday
False

भले ही सोमवार का सेशन लम्बा हो, तुलना बताती है कि वह बुधवार से छोटा है। कारण यह है कि Python स्ट्रिंग तुलना में “25” “27” से पहले आता है।

तो, फील्ड्स का क्रम बनाए रखते हुए सेशंस को वर्कआउट ड्यूरेशन के आधार पर कैसे सॉर्ट करें? यह field फ़ंक्शन से सरल है:

@dataclass(order=True)
class WorkoutSession:
   date: str = field(default=None, compare=False)
   exercises: List[Exercise] = field(default_factory=create_warmup)
   duration_minutes: int = 5

   ...

hiit_monday = WorkoutSession("25-02-2024")
hiit_monday.increase_duration(10)

hiit_wednesday = WorkoutSession("27-02-2024")

hiit_monday > hiit_wednesday
True

किसी भी फील्ड के लिए compare को False करने से हम उसे सॉर्टिंग से बाहर कर देते हैं, जैसा कि ऊपर के परिणाम से साबित है।

पोस्ट-इनिट फील्ड मैनिप्युलेशन

अभी, वार्म-अप एक्सरसाइज़ को ध्यान में रखते हुए हमारे पास पाँच मिनट का डिफॉल्ट सेशन ड्यूरेशन है। लेकिन यह तभी तर्कसंगत है जब यूज़र सेशन वार्म-अप से शुरू करे। अगर वे अन्य एक्सरसाइज़ से शुरू करें तो क्या होगा:

new_session = WorkoutSession([Exercise("Diamond push-ups", 10, 3)])

new_session.duration_minutes
5

सिर्फ एक एक्सरसाइज़ के लिए कुल ड्यूरेशन पाँच मिनट होना तर्कसंगत नहीं। हर सेशन को हर एक्सरसाइज़ के सेटों की संख्या के आधार पर अपना ड्यूरेशन डायनेमिक रूप से अनुमान लगाना चाहिए। यानी duration_minutes को exercises फील्ड पर निर्भर होना चाहिए।

आइए इसे इम्प्लीमेंट करें:

@dataclass
class WorkoutSession:
   exercises: List[Exercise] = field(default_factory=create_warmup)
   duration_minutes: int = field(default=0, init=False)

   def __post_init__(self):
       set_duration = 3
       for ex in self.exercises:
           self.duration_minutes += ex.sets * set_duration

   ...

इस बार, हम duration_minutes को init को False रखकर परिभाषित कर रहे हैं ताकि फील्ड का इनिशियलाइज़ेशन टाला जा सके।

फिर, विशेष मेथड __post_init__ के अंदर, हम इसके मान को हर Exercise के कुल सेटों के आधार पर अपडेट कर रहे हैं।

अब, जब हम WorkoutSession इनिशियलाइज़ करते हैं, तो duration_minutes हर एक्सरसाइज़ के हर सेट के लिए तीन मिनट से डायनेमिक रूप से बढ़ता है।

# Adding an exercise with three sets
hiit_friday = WorkoutSession([Exercise("Diamond push-ups", 10, 3)])

hiit_friday.duration_minutes
9

सामान्यतः, यदि आप ऐसा फील्ड परिभाषित करना चाहते हैं जो आपकी डेटा क्लास के अन्य फील्ड्स पर निर्भर हो, तो आप __post_init__ लॉजिक का उपयोग कर सकते हैं।

डेटा क्लासेस में इम्यूटेबिलिटी

हमारी WorkoutSession डेटा क्लास लगभग तैयार है; बस इसे सुरक्षित करना है। अभी, इसे आसानी से बिगाड़ा जा सकता है:

hiit_friday.duration_minutes = 1000

hiit_friday.duration_minutes
1000

del hiit_friday.exercises

हम अपनी क्लासेस के सभी फील्ड्स को इस तरह सुरक्षित करना चाहते हैं कि उन्हें केवल हमारे इच्छित तरीके से ही बदला जा सके। इसे प्राप्त करने के लिए, @dataclass डेकोरेटर एक सुविधाजनक frozen आर्ग्युमेंट देता है:

@dataclass(frozen=True)
class FrozenExercise:
   name: str
   reps: int
   sets: int
   weight: int | float = 0


ex1 = FrozenExercise("Muscle-ups", 5, 3)

अब, अगर हम कोई भी फील्ड बदलना चाहें, तो एरर मिलता है:

ex1.sets = 5
FrozenInstanceError: cannot assign to field 'sets'

frozen को True करने से हर फील्ड के लिए __deleteattr__ और __setattr__ मेथड अपने-आप जुड़ जाते हैं ताकि इनिशियलाइज़ेशन के बाद उन्हें डिलीट या अपडेट होने से बचाया जा सके। साथ ही, दूसरे लोग नए फील्ड भी नहीं जोड़ पाएँगे:

ex1.new_field = 10
FrozenInstanceError: cannot assign to field 'new_field'

पारंपरिक क्लासेस में यही कार्यक्षमता दर्जनों पंक्तियों में जाती।

हालाँकि, ध्यान दें कि हम अपनी क्लासेस को सच में इम्यूटेबल नहीं बना सकते। उदाहरण के लिए, WorkoutSession को frozen को True कर के फिर से लिखते हैं:

@dataclass(frozen=True)
class ImmutableWorkoutSession:
   exercises: List[Exercise] = field(default_factory=create_warmup)
   duration_minutes: int = 5


session1 = ImmutableWorkoutSession()

अपेक्षित रूप से, हम एक्सरसाइज़ की सूची को सीधे संशोधित नहीं कर सकते:

session1.exercises = [Exercise()]

लेकिन, exercises एक सूची है, जो पूरी तरह म्यूटेबल है, जिससे नीचे का ऑपरेशन संभव हो जाता है:

# सूची के एक एलिमेंट को बदलना

# Changing one of the elements in a list
session1.exercises[1] = FrozenExercise("Totally new exercise", 5, 5)

print(session1)

ImmutableWorkoutSession(exercises=[Exercise(name='Jumping jacks', reps=30, sets=1, weight=0), FrozenExercise(name='Totally new exercise', reps=5, sets=5, weight=0), Exercise(name='High jumps', reps=20, sets=1, weight=0)], duration_minutes=5)

इसलिए, आकस्मिक बदलावों से बचाने के लिए, फील्ड वैल्यू के लिए tuples जैसे इम्यूटेबल ऑब्जेक्ट्स का उपयोग करने की सिफारिश की जाती है।

डेटा क्लासेस में इनहेरिटेंस

अंत में, हम पैरेंट और चाइल्ड क्लासेस में फील्ड्स के क्रम को कवर करेंगे।

क्योंकि डेटा क्लासेस सामान्य क्लासेस हैं, इनहेरिटेंस सामान्य रूप से काम करता है:

@dataclass(frozen=True)
class ImmutableWorkoutSession:
   exercises: List[Exercise] = field(default_factory=create_warmup)
   duration_minutes: int = 5


@dataclass(frozen=True)
class CardioWorkoutSession(ImmutableWorkoutSession):
   pass

लेकिन, क्योंकि पैरेंट क्लास (ImmutableWorkoutSession) का अंतिम फील्ड डिफॉल्ट वैल्यू रखता है, चाइल्ड क्लासेस के सभी फील्ड्स में भी डिफॉल्ट वैल्यू होनी चाहिए।

उदाहरण के लिए, यह अनुमति नहीं है:

@dataclass(frozen=True)
class ImmutableWorkoutSession:
   exercises: List[Exercise] = field(default_factory=create_warmup)
   duration_minutes: int = 5


@dataclass(frozen=True)
class CardioWorkoutSession(ImmutableWorkoutSession):
   intensity_level: str  # Not allowed, must have a default

TypeError: non-default argument 'intensity_level' follows default argument

डेटा क्लासेस की कमियाँ और आगे के संसाधन

Python 3.7 से डेटा क्लासेस लगातार बेहतर होती गई हैं (शुरू से ही बेहतरीन थीं) और उन कई उपयोग मामलों को कवर करती हैं जहाँ आपको क्लासेस लिखने की ज़रूरत पड़ती है। लेकिन ये निम्न परिदृश्यों में कम अनुकूल हो सकती हैं:

  • कस्टम __init__ मेथड्स
  • कस्टम __new__ मेथड्स
  • विभिन्न इनहेरिटेंस पैटर्न

और भी बहुत से, जिन पर इस बेहतरीन Reddit थ्रेड में चर्चा है। यदि आप यह विस्तार से समझना चाहते हैं कि डेटा क्लासेस क्यों पेश की गईं और वे सामान्य क्लास डेफिनिशन का ड्रॉप-इन रिप्लेसमेंट क्यों नहीं हैं, तो PEP 557 पढ़ें।

यदि आप सामान्य रूप से ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में रुचि रखते हैं, तो अपनी यात्रा आगे बढ़ाने के लिए यह कोर्स देखें:

मूलतः, डेटा क्लासेस डेटा को अधिक कुशलता से रखने और प्राप्त करने की थोड़ी ज्यादा परिष्कृत संरचनाएँ हैं। हालाँकि, Python में कई अन्य डेटा स्ट्रक्चर हैं जो यह काम कमोबेश इसी तरह करते हैं। उदाहरण के लिए, आप Data Types for Data Science कोर्स के आखिरी अध्याय में counters, defaultdicts और namedtuples के बारे में सीख सकते हैं।

Bexruz (Bex) Tuychiev

लेखक

Bexruz (Bex) Tuychiev

मैं 2 से अधिक वर्षों के अनुभव वाला डेटा साइंस कंटेंट क्रिएटर हूँ और Medium पर सबसे बड़े फॉलोइंग्स में से एक रखता हूँ। मुझे एआई और एमएल पर विस्तार से लेख लिखना पसंद है, जिसमें हल्का-सा व्यंग्यात्मक अंदाज रहता है—क्योंकि कुछ तो करना पड़ता है ताकि वे कम उबाऊ लगें। मैंने 130 से अधिक लेख और एक DataCamp कोर्स तैयार किया है, और एक और बन रहा है। मेरा कंटेंट 50 लाख से अधिक लोगों ने देखा है, जिनमें से 20 हज़ार लोग Medium और LinkedIn पर फॉलोअर्स बन गए। 

विषय