कम से कम पांच छह तरीके हैं। पसंदीदा तरीका इस बात पर निर्भर करता है कि आपका उपयोग मामला क्या है।
विकल्प 1: बस एक asdict()विधि जोड़ें ।
समस्या वर्णन के आधार पर मैं asdictअन्य उत्तरों द्वारा सुझाई गई चीजों को करने के तरीके पर बहुत विचार करूंगा । ऐसा इसलिए है क्योंकि ऐसा नहीं लगता है कि आपकी वस्तु वास्तव में बहुत अधिक है:
class Wharrgarbl(object):
...
def asdict(self):
return {'a': self.a, 'b': self.b, 'c': self.c}
नीचे दिए गए अन्य विकल्पों का उपयोग करना दूसरों के लिए भ्रामक हो सकता है जब तक कि यह बिल्कुल स्पष्ट न हो कि कौन से वस्तु सदस्य मुख्य-मूल्य जोड़े के रूप में iterated या निर्दिष्ट नहीं होंगे।
विकल्प 1a: अपनी कक्षा को 'typing.NamedTuple'(या अधिकतर समतुल्य 'collections.namedtuple') इनहेरिट करें , और आपके लिए दी गई _asdictविधि का उपयोग करें ।
from typing import NamedTuple
class Wharrgarbl(NamedTuple):
a: str
b: str
c: str
sum: int = 6
version: str = 'old'
एक नामित टपल का उपयोग सहित प्रयास की एक न्यूनतम, के साथ अपने वर्ग के लिए कार्यक्षमता के बहुत सारे जोड़ने के लिए एक बहुत ही सुविधाजनक तरीका है एक _asdictविधि । हालाँकि, एक सीमा यह है कि जैसा कि ऊपर दिखाया गया है, NT सभी सदस्यों को इसमें शामिल करेगा _asdict।
यदि ऐसे सदस्य हैं जिन्हें आप अपने शब्दकोश में शामिल नहीं करना चाहते हैं, तो आपको _asdictपरिणाम को संशोधित करना होगा :
from typing import NamedTuple
class Wharrgarbl(NamedTuple):
a: str
b: str
c: str
sum: int = 6
version: str = 'old'
def _asdict(self):
d = super()._asdict()
del d['sum']
del d['version']
return d
एक और सीमा यह है कि NT केवल-पढ़ने के लिए है। यह वांछनीय हो सकता है या नहीं भी हो सकता है।
विकल्प 2: लागू करें __iter__।
इस तरह, उदाहरण के लिए:
def __iter__(self):
yield 'a', self.a
yield 'b', self.b
yield 'c', self.c
अब आप बस कर सकते हैं:
dict(my_object)
यह काम करता है क्योंकि निर्माणकर्ता एक शब्दकोश बनाने के लिए जोड़े के dict()चलने योग्य स्वीकार करता है (key, value)। ऐसा करने से पहले, अपने आप से यह सवाल पूछें कि क्या वस्तु को श्रृंखला की कुंजी के रूप में पुनरावृत्त करना, इस तरह से मूल्य जोड़े- जबकि बनाने के लिए सुविधाजनक है dict- वास्तव में अन्य संदर्भों में आश्चर्यजनक व्यवहार हो सकता है। उदाहरण के लिए, अपने आप से सवाल पूछें "व्यवहार क्या होना list(my_object)चाहिए ...?"
इसके अतिरिक्त, ध्यान दें कि प्राप्त आइटम obj["a"]सिंटैक्स का उपयोग करके सीधे मानों तक पहुंचने से काम नहीं चलेगा, और कीवर्ड तर्क अनपैकिंग काम नहीं करेगा। उन लोगों के लिए, आपको मैपिंग प्रोटोकॉल लागू करना होगा।
विकल्प 3: मैपिंग प्रोटोकॉल को लागू करें । यह एक्सेस-बाय-कुंजी व्यवहार की अनुमति देता है, बिना उपयोग किए कास्टिंग करता है, और यदि सभी कुंजी स्ट्रिंग ( ) हैं, तो भी अनपैकिंग व्यवहार ( ) और कीवर्ड अनपैकिंग व्यवहार प्रदान करता है ।dict__iter__{**my_obj}dict(**my_obj)
मैपिंग प्रोटोकॉल के लिए आवश्यक है कि आप (न्यूनतम) दो तरीके एक साथ प्रदान करें: keys()और __getitem__।
class MyKwargUnpackable:
def keys(self):
return list("abc")
def __getitem__(self, key):
return dict(zip("abc", "one two three".split()))[key]
अब आप निम्न कार्य कर सकते हैं:
>>> m=MyKwargUnpackable()
>>> m["a"]
'one'
>>> dict(m)
{'a': 'one', 'b': 'two', 'c': 'three'}
>>> dict(**m)
{'a': 'one', 'b': 'two', 'c': 'three'}
जैसा कि ऊपर उल्लेख किया गया है, यदि आप अजगर के एक नए पर्याप्त संस्करण का उपयोग कर रहे हैं, तो आप अपनी मैपिंग-प्रोटोकॉल ऑब्जेक्ट को एक शब्दकोश समझ में भी अनपैक कर सकते हैं (और इस मामले में यह आवश्यक नहीं है कि आपकी चाबियाँ तार हों):
>>> {**m}
{'a': 'one', 'b': 'two', 'c': 'three'}
ध्यान दें कि मानचित्रण प्रोटोकॉल पर पूर्वता लेता है__iter__ जब एक के लिए एक वस्तु कास्टिंग विधि dictसीधे (kwarg खोल का उपयोग किए बिना, यानी dict(m))। इसलिए यह संभव है- और कभी-कभी सुविधाजनक- वस्तु को एक व्यवहार योग्य (जैसे, list(m)) बनाम बनाम जब एक dict( dict(m)) के रूप में इस्तेमाल किया जाता है, तो अलग व्यवहार का कारण बनता है ।
पर बल दिया : सिर्फ इसलिए कि आप मानचित्रण प्रोटोकॉल का उपयोग कर सकते हैं, इसका मतलब यह नहीं है कि आप करना चाहिए ऐसा करने के । क्या यह वास्तव मेंआपकी वस्तु के लिए कुंजी-मूल्य जोड़े के एक समूह के रूप में, या खोजशब्द तर्क और मूल्यों के रूप में पारित होने के लिए समझ में आता है ? क्या इसे कुंजी द्वारा एक्सेस करना- एक शब्दकोश की तरह- वास्तव में समझ में आता है?
यदि इन सवालों का जवाब हां है , तो शायद अगले विकल्प पर विचार करना एक अच्छा विचार है।
विकल्प 4: 'collections.abc'मॉड्यूल का उपयोग करके देखें ।
अपनी कक्षा को अन्य उपयोगकर्ताओं के लिए 'collections.abc.Mappingया 'collections.abc.MutableMappingसंकेतों से इनहेरिट करना , जो सभी इरादों और उद्देश्यों के लिए है, आपकी कक्षा एक मैपिंग है * और उससे इस तरह के व्यवहार की उम्मीद की जा सकती है।
आप अभी भी अपनी dictआवश्यकता के अनुसार अपनी वस्तु को डाल सकते हैं , लेकिन ऐसा करने का बहुत कम कारण होगा। की वजह से बतख टाइपिंग , एक करने के लिए अपने मानचित्रण वस्तु कास्ट करने के लिए परेशान कर dictसिर्फ एक अतिरिक्त अनावश्यक कदम समय के बहुमत होगा।
यह उत्तर भी सहायक हो सकता है।
जैसा कि नीचे टिप्पणी में उल्लेख किया गया है: यह ध्यान देने योग्य है कि ऐसा करने से एबीसी रास्ता अनिवार्य रूप से आपके ऑब्जेक्ट क्लास को एक समान श्रेणी में बदल देता है dict(यह मानते हुए कि आप उपयोग करते हैं MutableMappingऔर केवल-पढ़ने के लिए Mappingआधार वर्ग नहीं)। सब कुछ आप के साथ करने में सक्षम हो जाएगा dict, आप अपनी कक्षा वस्तु के साथ कर सकते हैं। यह वांछनीय हो सकता है या नहीं भी हो सकता है।
numbersमॉड्यूल में संख्यात्मक एब्स को देखने पर भी विचार करें :
https://docs.python.org/3/library/numbers.html
चूँकि आप अपनी वस्तु को किसी को भी कास्टिंग कर रहे हैं int, इसलिए यह आवश्यक रूप से आपकी कक्षा को पूर्ण रूप से बदल देने में मदद कर सकता है intताकि कास्टिंग आवश्यक न हो।
विकल्प 5: dataclassesमॉड्यूल (केवल पायथन 3.7) का उपयोग करके देखें , जिसमें एक सुविधाजनक asdict()उपयोगिता विधि शामिल है।
from dataclasses import dataclass, asdict, field, InitVar
@dataclass
class Wharrgarbl(object):
a: int
b: int
c: int
sum: InitVar[int]
version: InitVar[str] = "old"
def __post_init__(self, sum, version):
self.sum = 6
self.version = str(version)
अब आप यह कर सकते हैं:
>>> asdict(Wharrgarbl(1,2,3,4,"X"))
{'a': 1, 'b': 2, 'c': 3}
विकल्प 6: उपयोग typing.TypedDict, जिसे अजगर 3.8 में जोड़ा गया है ।
ध्यान दें: विकल्प 6 संभावना नहीं है कि इस प्रश्न के शीर्षक के आधार पर ओपी, या अन्य पाठक क्या देख रहे हैं। नीचे अतिरिक्त टिप्पणियां देखें।
class Wharrgarbl(TypedDict):
a: str
b: str
c: str
इस विकल्प का उपयोग करते हुए, परिणामी वस्तु एकdict (जोर: यह नहीं है Wharrgarbl)। वहाँ कोई कारण नहीं है कि इसे "कास्ट" किया जाए (जब तक कि आप प्रतिलिपि नहीं बना रहे)।
और चूंकि ऑब्जेक्ट एक हैdict , इनिशियलाइज़ेशन सिग्नेचर के समान है dictऔर जैसे कि यह केवल कीवर्ड तर्क या किसी अन्य शब्दकोश को स्वीकार करता है।
>>> w = Wharrgarbl(a=1,b=2,b=3)
>>> w
{'a': 1, 'b': 2, 'c': 3}
>>> type(w)
<class 'dict'>
जोर दिया : उपरोक्त "वर्ग" Wharrgarblवास्तव में एक नया वर्ग नहीं है। यह बस टाइपकर्ता के लिए dictविभिन्न प्रकार के क्षेत्रों के साथ टाइप किए गए ऑब्जेक्ट बनाने के लिए सिंटैक्टिक चीनी है ।
जैसे कि यह विकल्प आपके कोड के पाठकों को संकेत देने के लिए बहुत सुविधाजनक हो सकता है (और एक प्रकार का चेकर जैसे कि मैपी भी) कि ऐसी dictवस्तु में विशिष्ट मूल्य प्रकारों के साथ विशिष्ट कुंजी होने की उम्मीद है।
लेकिन इसका मतलब है कि आप उदाहरण के लिए, अन्य तरीकों को नहीं जोड़ सकते, हालांकि आप कोशिश कर सकते हैं:
class MyDict(TypedDict):
def my_fancy_method(self):
return "world changing result"
... लेकिन यह काम नहीं करेगा:
>>> MyDict().my_fancy_method()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'my_fancy_method'
* "मैपिंग" मानक dict-प्रकार के बतख के प्रकार का "नाम" बन गया है