Python Academy · पाठ

कस्टम मेटाक्लास लिखना

क्लास निर्माण को अनुकूलित करने के लिए मेटाक्लास में __new__ और __init__ का उपयोग करें।

पाठ 2, कुल 4 में से13 चरण

कस्टम मेटाक्लास लिखना, CoddyKit पर Python Academy का एक निःशुल्क पाठ है। यह 4 में से 2वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह Python Academy सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। Python Academy पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

मेटाक्लास घोषित करना

कस्टम मेटाक्लास का उपयोग करने के लिए क्लास की परिभाषा में metaclass=MyMeta पास करें। मेटाक्लास को type से विरासत में मिलना चाहिए।

class MyMeta(type):
    pass

class Foo(metaclass=MyMeta):
    pass

print(type(Foo))   # <class '__main__.MyMeta'>

__new__ को ओवरराइड करना

__new__(mcs, name, bases, namespace) क्लास ऑब्जेक्ट बनाता है। क्लास बनने से पहले नेमस्पेस को संशोधित करने के लिए इसका उपयोग करें।

class UpperAttrMeta(type):
    def __new__(mcs, name, bases, namespace):
        upper = {k.upper(): v for k, v in namespace.items()
                 if not k.startswith("_")}
        return super().__new__(mcs, name, bases, {**namespace, **upper})

class Config(metaclass=UpperAttrMeta):
    debug = True

print(Config.DEBUG)  # True

__init__ को ओवरराइड करना

__init__(cls, name, bases, namespace) क्लास बनने के बाद चलता है। पंजीकरण जैसे निर्माण-पश्चात सेटअप के लिए इसका उपयोग करें।

_registry = {}

class AutoRegisterMeta(type):
    def __init__(cls, name, bases, namespace):
        super().__init__(name, bases, namespace)
        if bases:   # skip the base class itself
            _registry[name] = cls

class Handler(metaclass=AutoRegisterMeta): pass
class JSONHandler(Handler): pass
class XMLHandler(Handler):  pass

print(_registry)  # {'JSONHandler': ..., 'XMLHandler': ...}

Interface अनुबंध लागू करना

यदि क्लास बॉडी में आवश्यक विधियाँ मौजूद न हों, तो __new__ में TypeError उठाएँ।

class InterfaceMeta(type):
    REQUIRED = frozenset({"process", "validate"})

    def __new__(mcs, name, bases, ns):
        if bases and not mcs.REQUIRED.issubset(ns):
            missing = mcs.REQUIRED - ns.keys()
            raise TypeError(f"{name} must define: {missing}")
        return super().__new__(mcs, name, bases, ns)

class Worker(metaclass=InterfaceMeta):
    def process(self): ...
    def validate(self): ...

मेटाक्लास के माध्यम से Singleton

इंस्टेंस निर्माण को बीच में रोकने और हर बार वही इंस्टेंस लौटाने के लिए मेटाक्लास पर __call__ को ओवरराइड करें।

class SingletonMeta(type):
    _instances = {}
    def __call__(cls, *a, **kw):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*a, **kw)
        return cls._instances[cls]

class DB(metaclass=SingletonMeta):
    pass

print(DB() is DB())  # True

विधियाँ गतिशील रूप से जोड़ना

मेटाक्लास का उपयोग करने वाली प्रत्येक क्लास में उपयोगिता विधियाँ डालें, बिना हर क्लास को अलग-अलग संशोधित किए।

class MethodInjectorMeta(type):
    def __new__(mcs, name, bases, ns):
        ns["describe"] = lambda self: f"I am {type(self).__name__}"
        return super().__new__(mcs, name, bases, ns)

class Widget(metaclass=MethodInjectorMeta):
    pass

print(Widget().describe())   # I am Widget

क्रमबद्ध नेमस्पेस के लिए __prepare__

क्लास नेमस्पेस के रूप में कस्टम मैपिंग देने के लिए __prepare__ को ओवरराइड करें, जैसे परिभाषा क्रम सुरक्षित रखने या डुप्लिकेट का पता लगाने के लिए।

class NoDuplicatesMeta(type):
    class _NS(dict):
        def __setitem__(self, k, v):
            if k in self and not k.startswith("_"):
                raise ValueError(f"Duplicate attribute: {k}")
            super().__setitem__(k, v)

    @classmethod
    def __prepare__(mcs, name, bases):
        return mcs._NS()

मेटाक्लास टकराव का समाधान

जब कई आधार क्लासों के मेटाक्लास अलग-अलग हों, तो Python स्पष्ट रूप से सबसे अधिक व्युत्पन्न मेटाक्लास का उपयोग करना आवश्यक करता है; अन्यथा टकराव की त्रुटि उत्पन्न होती है।

class MetaA(type): pass
class MetaB(type): pass

# class Bad(A, B): pass  # TypeError: metaclass conflict

class MetaAB(MetaA, MetaB): pass   # resolve manually

class A(metaclass=MetaA): pass
class B(metaclass=MetaB): pass
class Good(A, B, metaclass=MetaAB): pass

मेटाक्लास बनाम __init_subclass__

उपक्लास पंजीकरण और साधारण हुक के लिए __init_subclass__ अधिक सरल है और इसमें मेटाक्लास की आवश्यकता नहीं होती।

class Base:
    _registry = []
    def __init_subclass__(cls, **kw):
        super().__init_subclass__(**kw)
        Base._registry.append(cls)

class ChildA(Base): pass
class ChildB(Base): pass

print(Base._registry)  # [ChildA, ChildB]

विशेषता पहुँच का अनुरेखण

क्लास की विशेषता तक पहुँच को बीच में रोकने के लिए मेटाक्लास पर __getattribute__ को ओवरराइड करें, इंस्टेंस की विशेषता पहुँच को नहीं।

class TraceMeta(type):
    def __getattribute__(cls, name):
        val = super().__getattribute__(name)
        if not name.startswith("_"):
            print(f"Accessing class attr: {name}")
        return val

class Config(metaclass=TraceMeta):
    HOST = "localhost"

_ = Config.HOST   # logs: Accessing class attr: HOST

ORM फ़ील्ड संग्रह पैटर्न

Django-शैली के ORM, क्लास बॉडी से Field डिस्क्रिप्टर एकत्र करके उन्हें _meta रजिस्ट्री में रखते हैं।

class Field:
    def __init__(self, col): self.col = col

class ModelMeta(type):
    def __new__(mcs, name, bases, ns):
        fields = {k: v for k, v in ns.items() if isinstance(v, Field)}
        ns["_fields"] = fields
        return super().__new__(mcs, name, bases, ns)

class User(metaclass=ModelMeta):
    name = Field("name")
    email = Field("email")

print(User._fields.keys())  # dict_keys(['name', 'email'])

त्वरित जाँच

कस्टम मेटाक्लास में, क्लास ऑब्जेक्ट बनाने के लिए स्वयं कौन-सी विधि __init__ से पहले कॉल की जाती है?

पुनरावलोकन

कस्टम मेटाक्लास क्लास निर्माण को नियंत्रित करने के लिए __new__/__init__ को ओवरराइड करते हैं: अनुबंध लागू करना, उपक्लासों का स्वचालित पंजीकरण, विधियाँ डालना या फ़ील्ड डिस्क्रिप्टर एकत्र करना। साधारण पंजीकरण आवश्यकताओं के लिए __init_subclass__ को प्राथमिकता दें।

शुरुआत निःशुल्क

एआई शिक्षक के साथ Python सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
76
पाठ
320

अक्सर पूछे जाने वाले प्रश्न

क्या “कस्टम मेटाक्लास लिखना” पाठ निःशुल्क है?

हाँ—“कस्टम मेटाक्लास लिखना” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और Python Academy पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। Python Academy पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“कस्टम मेटाक्लास लिखना” में मैं क्या सीखूँगा?

क्लास निर्माण को अनुकूलित करने के लिए मेटाक्लास में __new__ और __init__ का उपयोग करें। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ Python Academy का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या Python Academy शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर Python Academy शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 2वाँ पाठ है।

“कस्टम मेटाक्लास लिखना” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस Python Academy पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर Python Academy पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. Python क्लास कैसे बनाई जाती हैं
  2. कस्टम मेटाक्लास लिखना
  3. डिस्क्रिप्टर: __get__, __set__, __delete__
  4. __slots__ और मेमोरी अनुकूलन
← Python Academy पर वापस जाएँ