मैं तो मैं यह थोड़ा पुनर्लेखन करने का निर्णय लिया पिछले जवाब के साथ एक सा निराश था:
from types import DynamicClassAttribute
# Metaclass
class Funny(type):
def __getattr__(self, value):
print('search in meta')
# Normally you would implement here some ifs/elifs or a lookup in a dictionary
# but I'll just return the attribute
return Funny.dynprop
# Metaclasses dynprop:
dynprop = 'Meta'
class Fun(metaclass=Funny):
def __init__(self, value):
self._dynprop = value
@DynamicClassAttribute
def dynprop(self):
return self._dynprop
और यहां "गतिशील" भाग आता है। आप वर्ग पर dynprop
फोन यदि यह मेटा में खोज और वापस आ जाएगी मेटा के dynprop
:
Fun.dynprop
जो प्रिंट:
search in meta
'Meta'
तो हम metaclass.__getattr__
लागू और मूल विशेषता लौटे (जो था नई संपत्ति के समान नाम से परिभाषित)।
उदाहरण के लिए Fun
-instance की dynprop
दिया जाता है जबकि:
Fun('Not-Meta').dynprop
हम ओवरराइड विशेषता मिलती है:
'Not-Meta'
इस से मेरा निष्कर्ष यह है कि DynamicClassAttribute
महत्वपूर्ण है अगर आप चाहते हैं मेटाक्लास में उपयोग किए जाने वाले समान नाम के साथ उप-वर्गों को एक विशेषता रखने की अनुमति देने के लिए। आप इसे उदाहरणों पर छाया देंगे लेकिन यदि आप इसे कक्षा में कॉल करते हैं तो यह अभी भी सुलभ है।
मैं पुराने संस्करण में Enum
के व्यवहार में चली गई तो मैं इसे यहाँ में छोड़ दिया:
पुराने संस्करण
DynamicClassAttribute
सिर्फ उपयोगी है (मैं उस बिंदु पर वास्तव में यकीन नहीं है) करता है, तो आपको संदेह है कि सबक्लस पर सेट की गई विशेषता और बेस-क्लास पर एक संपत्ति के बीच संघर्ष का नाम हो सकता है।
क्योंकि इस metaclasses (पर कैसे वर्ग गुण कहा जाता है एक अच्छा स्पष्टीकरण this blog post में पाया जा सकता) का उपयोग किए बिना काम नहीं करेगा क्योंकि विशेषता देखने थोड़ा अलग है आप, metaclasses के बारे में कम से कम कुछ मूल बातें पता करने की आवश्यकता होगी metaclasses के साथ।
मान लीजिए आपके पास:
class Funny(type):
dynprop = 'Very important meta attribute, do not override'
class Fun(metaclass=Funny):
def __init__(self, value):
self._stub = value
@property
def dynprop(self):
return 'Haha, overridden it with {}'.format(self._stub)
और फिर कहते हैं:
Fun.dynprop
0x1b3d9fd19a8
पर संपत्ति और उदाहरण पर हम पाते हैं:
Fun(2).dynprop
बुरा 'Haha, यह 2 के साथ अधिरोहित' ... यह खो जाता है। लेकिन प्रतीक्षा करें कि हम metaclass
विशेष लुकअप का उपयोग कर सकते हैं: चलो __getattr__
(फ़ॉलबैक) लागू करें और dynprop
को DynamicClassAttribute
के रूप में कार्यान्वित करें।क्योंकि यह के अनुसार documentation है कि अपने उद्देश्य है - __getattr__
पर वापस आने की अगर यह वर्ग पर कहा जाता है:
Fun.dynprop
जो प्रिंट:
search in meta
'Meta'
from types import DynamicClassAttribute
class Funny(type):
def __getattr__(self, value):
print('search in meta')
return Funny.dynprop
dynprop = 'Meta'
class Fun(metaclass=Funny):
def __init__(self, value):
self._dynprop = value
@DynamicClassAttribute
def dynprop(self):
return self._dynprop
अब हम वर्ग विशेषता का उपयोग
इसलिए हमने metaclass.__getattr__
का आह्वान किया और मूल विशेषता को वापस कर दिया (जिसे नई संपत्ति के समान नाम से परिभाषित किया गया था)।
और उदाहरण के लिए:
'Not-Meta'
खैर कि विचार हम उदाहरण बनाकर बिना पहले से परिभाषित लेकिन ओवरराइड विशेषताओं के metaclasses का उपयोग कर कहीं और भेजें कर सकते हैं बहुत बुरा नहीं है:
Fun('Not-Meta').dynprop
हम ओवरराइड विशेषता मिलता है।
from enum import Enum
class Fun(Enum):
name = 'me'
age = 28
hair = 'brown'
और डिफ़ॉल्ट रूप से इन बाद में परिभाषित विशेषताओं का उपयोग करना चाहते हैं: यह उदाहरण विपरीत कि Enum
है, जहां आप उपवर्ग पर विशेषताएं निर्धारित के साथ किया जाता है।
Fun.name
# <Fun.name: 'me'>
लेकिन आप यह भी name
विशेषता है कि DynamicClassAttribute
के रूप में परिभाषित किया गया था (जो देता है जो नाम चर वास्तव में है) तक पहुँचने की अनुमति देना चाहते:
Fun('me').name
# 'name'
क्योंकि अन्यथा आप कैसे 28
के नाम का उपयोग कर सकता है ?
Fun.hair.age
# <Fun.age: 28>
# BUT:
Fun.hair.name
# returns 'hair'
अंतर देखें? दूसरा <Fun.name: 'me'>
क्यों नहीं लौटाता है? यह DynamicClassAttribute
के उपयोग के कारण है। तो आप मूल संपत्ति को छाया कर सकते हैं लेकिन बाद में इसे "रिलीज़" कर सकते हैं। यह व्यवहार मेरे उदाहरण में दिखाया गया है और कम से कम __new__
और __prepare__
के उपयोग की आवश्यकता है। लेकिन इसके लिए आपको यह जानने की ज़रूरत है कि यह वास्तव में कैसे काम करता है और कई ब्लॉगों और स्टैक ओवरफ्लो-उत्तरों में समझाया गया है जो मुझे इससे बेहतर समझा सकता है, इसलिए मैं उस गहराई में जा रहा हूं (और मुझे यकीन नहीं है कि मैं इसे कम क्रम में हल कर सकता हूं)।
वास्तविक उपयोग-मामले विरल लेकिन निश्चित समय एक propably कुछ के बारे में सोच सकते हैं हो सकता है ... DynamicClassAttribute
के प्रलेखन पर
बहुत अच्छा चर्चा: "we added it because we needed it"