अजगर में, मैंने एक वर्ग वस्तु को एक तानाशाह को कैसे दिया


85

मान लीजिए कि मुझे अजगर में एक साधारण वर्ग मिला है

class Wharrgarbl(object):
    def __init__(self, a, b, c, sum, version='old'):
        self.a = a
        self.b = b
        self.c = c
        self.sum = 6
        self.version = version

    def __int__(self):
        return self.sum + 9000

    def __what_goes_here__(self):
        return {'a': self.a, 'b': self.b, 'c': self.c}

मैं इसे बहुत आसानी से एक पूर्णांक में डाल सकता हूं

>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> int(w)
9006

जो माहान है! लेकिन, अब मैं इसे उसी अंदाज में डिक्टेट करना चाहता हूं

>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> dict(w)
{'a': 'one', 'c': 'three', 'b': 'two'}

इसे काम करने के लिए मुझे क्या परिभाषित करने की आवश्यकता है? मैं दोनों के लिए __dict__और के dictलिए प्रतिस्थापन की कोशिश की __what_goes_here__, लेकिन दोनों मामलों dict(w)में एक परिणाम है TypeError: Wharrgarbl object is not iterable। मुझे नहीं लगता कि बस वर्ग को चलने योग्य बनाने से समस्या हल हो जाएगी। मैंने भी कई गुगलों के साथ "पिथोन कास्ट ऑब्जेक्ट टू डिक्टेड" के कई अलग-अलग शब्दों के साथ प्रयास किया, जैसा कि मैं सोच सकता था, लेकिन प्रासंगिक कुछ भी नहीं मिल सका: {

इसके अलावा! ध्यान दें कि कॉलिंग w.__dict__वह नहीं करेगी जो मैं चाहता हूं क्योंकि इसमें शामिल होना है w.versionऔर w.sum। मैं कास्ट को dictउसी तरह कस्टमाइज़ करना चाहता हूं जिस तरह से मैं कास्ट को कस्टमाइज़ intकरके इस्तेमाल कर सकता हूं def int(self)।

मुझे पता है कि मैं बस कुछ ऐसा कर सकता था

>>> w.__what_goes_here__()
{'a': 'one', 'c': 'three', 'b': 'two'}

लेकिन मैं यह मान रहा हूं कि dict(w)काम करने का एक पैथोनिक तरीका है क्योंकि यह उसी प्रकार की चीज है जैसे int(w)या str(w)। अगर वहाँ एक अधिक pythonic तरीका नहीं है, यह भी ठीक है, बस मुझे लगा कि मैं पूछना होगा। ओह! मुझे लगता है कि यह मायने रखता है, यह अजगर 2.7 के लिए है, लेकिन 2.4 पुराने और बस्टेड समाधान के लिए सुपर बोनस अंक भी।

अजगर वर्ग पर एक और सवाल ओवरलोडिंग __dict __ () है जो इस एक के समान है, लेकिन यह डुप्लिकेट नहीं होने के लिए वारंट के लिए पर्याप्त हो सकता है। मेरा मानना ​​है कि ओपी पूछ रहा है कि अपनी कक्षा की वस्तुओं में सभी डेटा को शब्दकोशों के रूप में कैसे डाला जाए। मैं एक और अधिक अनुकूलित दृष्टिकोण की तलाश कर रहा हूं, जिसमें मैं वह सब कुछ नहीं चाहता __dict__जो शब्दकोश में शामिल है dict()। पब्लिक बनाम प्राइवेट वैरिएबल जैसी कोई चीज यह समझाने के लिए पर्याप्त हो सकती है कि मैं क्या देख रहा हूं। वस्तुओं की गणना में उपयोग किए जाने वाले कुछ मूल्यों को संग्रहीत किया जाएगा और इस तरह कि मुझे परिणामी शब्दकोशों में दिखाने की आवश्यकता नहीं है।

अद्यतन: मैंने asdictसुझाए गए मार्ग के साथ जाने के लिए चुना है, लेकिन यह एक कठिन विकल्प था कि मैं इस प्रश्न का उत्तर क्या चाहता हूं। @RickTeachey और @ jpmc26 दोनों ने जवाब दिया कि मैं इसके साथ रोल करने जा रहा हूं, लेकिन पूर्व में अधिक जानकारी और विकल्प थे और उसी परिणाम पर उतरा और अधिक उत्थान किया गया इसलिए मैं इसके साथ गया। हालांकि चारों ओर अपवोट्स और मदद के लिए धन्यवाद। मैंने स्टैकओवरफ्लो पर लम्बा और कठोर पैर किया है और मैं अपने पैर की उंगलियों को पानी में लाने की कोशिश कर रहा हूं।


1
क्या आपने यह पहले से देखा है? docs.python.org/3/reference/…
— Garrett R

@GarrettR यह मददगार है, लेकिन यह वास्तव में इस विशेष मुद्दे में बहुत सारी जानकारी को प्रकट नहीं करता है।
— Zizouz212


@ रिकेटी यह निश्चित रूप से ओवरलोडिंग के समान है ... सवाल, हालांकि मैं एक अधिक अनुकूलन योग्य प्रतिनिधित्व की तलाश कर रहा हूं। उदाहरण के लिए, वस्तु उन चीज़ों को संग्रहीत कर सकती है जिन्हें मैं ध्यान में नहीं रखता हूँ।
— पेन्सेंट

आपका प्रश्न गुमराह करने वाला है, आप अपनी वस्तु को प्रतिष्ठित प्रतिनिधित्व में बदलना या डालना नहीं चाहते हैं (जैसे कि आप वस्तु को पूरी तरह से ठीक कर सकते हैं यदि आप वापस परिवर्तित हो गए हैं)। आप केवल (उदाहरण के लिए) सार्वजनिक उदाहरण चर के लिए एक प्रतिष्ठित प्रतिनिधित्व दृश्य बनाना चाहते हैं।
— एसएमसीआई

जवाबों:


117

कम से कम पांच छह तरीके हैं। पसंदीदा तरीका इस बात पर निर्भर करता है कि आपका उपयोग मामला क्या है।

विकल्प 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)  # cast to dict directly
{'a': 'one', 'b': 'two', 'c': 'three'}
>>> dict(**m)  # unpack as kwargs
{'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]  # note: InitVar will exclude this from the dict
    version: InitVar[str] = "old"

    def __post_init__(self, sum, version):
        self.sum = 6  # this looks like an OP mistake?
        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-प्रकार के बतख के प्रकार का "नाम" बन गया है


1
यह ओपी के प्रभाव को प्राप्त करने का एक तरीका है, लेकिन आपको यह स्पष्ट करना चाहिए कि इसके अन्य प्रभाव for k, v in my_objectभी हैं , उदाहरण के लिए भी सक्षम किया जाएगा।
— zwol

@ रिकेटी मैं देख रहा हूं कि आप क्या कर रहे हैं। मुझे निश्चित रूप से वस्तुओं को चलने की आवश्यकता नहीं है।
— लगन

हम अन्य लिंकहॉट्स में उल्लिखित vars फ़ंक्शन का उपयोग क्यों कर सकते हैं: //stackoverflow.com/questions/61517/python-dEDIA-from-an-objects-fields। क्या मुझे इस सवाल में कोई बात याद आ रही है?
— उपयोगकर्ता

@user ओपी के सवाल करना चाहता था केवल सदस्यों a, bऔर cमें dict। varsसमारोह जो कि चाहता था नहीं थे सहित वस्तु सदस्यों में से सभी के साथ एक शब्दकोश वापस आ जाएगी: sumऔर version। कुछ मामलों varsमें काम करेंगे लेकिन यह वास्तव में मेरे अनुभव में मुहावरेदार नहीं है। आमतौर पर लोग यह कहते हुए अधिक स्पष्ट होते हैं कि, "मैं अब अपनी वस्तु को एक शब्दकोश में ढाल रहा हूं" जैसे obj.asdict()। इसके साथ vars, यह आमतौर पर कुछ और पसंद obj_kwargs = vars(obj)है MyObject(**obj_kwargs)। दूसरे शब्दों में: varsअधिकतर वस्तुओं को कॉपी करने के लिए उपयोग किया जाता है।
— रिक मोनिका

कैसे एक विधि है कि रिटर्न के बारे में जोड़ने self.__dict__?
— user32882

17

कोई जादू की विधि नहीं है जो आप चाहते हैं। जवाब बस नाम है यह उचित है। मुख्य रूप से प्रेरित, asdictसादे रूपांतरण के लिए एक उचित विकल्प dictहै namedtuple। हालाँकि, आपकी विधि में स्पष्ट रूप से विशेष तर्क होंगे जो उस नाम से तुरंत स्पष्ट नहीं हो सकते हैं; आप केवल कक्षा के राज्य का एक सबसेट लौटा रहे हैं। यदि आप थोड़ा और क्रिया नाम के साथ आ सकते हैं जो अवधारणाओं को स्पष्ट रूप से संचार करता है, तो सभी बेहतर।

अन्य उत्तर का उपयोग करने का सुझाव देते हैं __iter__, लेकिन जब तक आपकी वस्तु वास्तव में चलने योग्य नहीं होती (तत्वों की एक श्रृंखला का प्रतिनिधित्व करती है), यह वास्तव में बहुत कम समझ में आता है और विधि का एक अजीब दुरुपयोग करता है। तथ्य यह है कि आप कक्षा के कुछ राज्य को फ़िल्टर करना चाहते हैं, इस दृष्टिकोण को और भी संदिग्ध बना देता है।


हां, कक्षा के पूरे राज्य का एक सबसेट लौटाकर, प्रासंगिकता के मूल्यों, वह है जो मैं हासिल करने की कोशिश कर रहा हूं। मुझे कुछ "छिपे हुए" मान मिले हैं जो चीजों को गणना / तुलना आदि के लिए तेज बनाते हैं, लेकिन वे कुछ भी नहीं हैं जो एक मानव देखना या खेलना चाहता है और वे वास्तव में स्वयं वस्तु का प्रतिनिधित्व नहीं करते हैं।
— पेन्सेंट

@ tr3buchet आपके उदाहरण कोड में, वे मान इनिशियलाइज़र को दिए जाते हैं । क्या यह आपके वास्तविक कोड में है? यह अजीब लगता है कि कैश्ड गणनाओं को तर्कों के रूप में पारित किया जाएगा।
— jpmc26

बिल्कुल नहीं, मैं सिर्फ एक उदाहरण प्रदान करने के लिए कर रहा था
— पेन्सेंट

बस यह नोट करना चाहते हैं कि डॉक्स__iter__ अन्य उत्तरों के रूप में सुझाए गए उपयोग करके कंडेन करने लगता है : "मैपिंग के लिए, इसे कंटेनर की चाबियों पर चलना चाहिए, और इसे विधि iterkeys () के रूप में भी उपलब्ध कराया जाना चाहिए।"
— dbenton

@dbenton वह नहीं है जो ओपी कर रहा है या अन्य उत्तर क्या सुझा रहे हैं। ओपी की वस्तु "कंटेनर" नहीं है, जो इस संदर्भ में मूल रूप से संग्रह के पर्याय के रूप में उपयोग किया जा रहा है। ओपी का उद्देश्य वह भी नहीं है जो आमतौर पर मैपिंग से होता है। एक मैपिंग कुछ ऐसी होगी जिसमें चाबियों और मूल्यों की एक मनमानी संख्या होती है और इसे Mappingआधार वर्ग का विस्तार करना चाहिए । विशिष्ट नाम वाली कोई वस्तु इस श्रेणी में नहीं आती है।
— jpmc26

11

ऐसा कुछ शायद काम करेगा

class MyClass:
    def __init__(self,x,y,z):
       self.x = x
       self.y = y
       self.z = z
    def __iter__(self): #overridding this to return tuples of (key,value)
       return iter([('x',self.x),('y',self.y),('z',self.z)])

dict(MyClass(5,6,7)) # because dict knows how to deal with tuples of (key,value)

ओह दिलचस्प! tuples के एक iterable, मैं इस पर विचार नहीं किया। मैं एक त्वरित परीक्षण करेंगे
— लगन

इसके अलावा, tuples की सूची के एक iter को x, y और z के सभी मानों को स्नैप करते हुए उस सूची में शामिल करें जिस पर यह iter आधारित है। यदि मामले में 3 उपज बयान करते हैं, तो यह संभव है (एक छोटी सी खिड़की, लेकिन फिर भी) जहां एक थ्रेडेड वातावरण में इसे चलाने से y विशेषता या z विशेषता को संशोधित करने वाले किसी अन्य थ्रेड में परिणाम हो सकता है जैसे कि रिपोर्ट की गई x, y और z संगत नहीं हैं।
— पॉलएमसीजी

@PaulMcGuire: क्या CPython गारंटी देता है कि वे सभी Joran के कोड के साथ भी सुसंगत रहेंगे? मैंने सोचा होगा कि एक और धागा शेड्यूल किया जा सकता है, उदाहरण के लिए, पहले टपल बनाने के बाद x, लेकिन दूसरे टपल के साथ y। क्या मैं गलत हूं, और वास्तव में सूची निर्धारण थ्रेड शेड्यूलिंग के संबंध में परमाणु है?
— स्टीव जेसप

अब जब आप पूछते हैं, तो मुझे एहसास होता है कि यहां तक ​​कि सूची की समझ भी परमाणु की गारंटी नहीं है, क्योंकि पायथन के थ्रेड स्विचर बाइटेकोड स्तर पर ऐसा करते हैं, न कि स्रोत स्तर पर। लेकिन आपका एक्सपोज़र केवल लिस्ट बनाने की अवधि के लिए है - एक बार लिस्ट बन जाने के बाद, प्रॉपर्टीज के लिए कोई भी अपडेट मायने नहीं रखेगा (जब तक कि प्रॉपर्टी वैल्यू म्यूटेबल ऑब्जेक्ट्स नहीं हैं)। disवास्तविक बायोटेक देखने के लिए मॉड्यूल का उपयोग करने के लिए सबसे अच्छा है।
— 19

11

मुझे लगता है कि यह आपके लिए काम करेगा।

class A(object):
    def __init__(self, a, b, c, sum, version='old'):
        self.a = a
        self.b = b
        self.c = c
        self.sum = 6
        self.version = version

    def __int__(self):
        return self.sum + 9000

    def __iter__(self):
        return self.__dict__.iteritems()

a = A(1,2,3,4,5)
print dict(a)

उत्पादन

{a ’: १, 'c’: 3,: b ’: 2,: sum’: 6,' version ’: 5}


योग और संस्करण का क्या हुआ? यह किसी भी __dict__अन्य सुझाव की तरह पहुँचने से अलग कैसे है ?
— जॉरन बेस्ले

यह तानाशाही नहीं है। पुनरावृत्तियों को कॉल पुनरावृत्ति देता है
— गैरेट R

1
मुझे यह उत्तर पसंद है ... लेकिन ओपी की आवश्यकताओं को पूरा करने से पहले इसे थोड़ा और काम करने की जरूरत है ...
— जॉरन बीस्ले

यह उत्तर वास्तव में @JoranBeasley से अलग नहीं है। अंतर यह है कि वह चयनात्मक है, जबकि आपकी संपूर्ण self.__dict__वस्तुएं जिसमें वे आइटम हैं जो मुझे ऑब्जेक्ट के शब्दकोश संस्करण में नहीं चाहिए।
— लगन

6

कई अन्य लोगों की तरह, मैं एक शब्दकोश में कास्टिंग करने की अनुमति देने के बजाय (या इसके अलावा) एक to_dict () फ़ंक्शन को लागू करने का सुझाव दूंगा। मुझे लगता है कि यह अधिक स्पष्ट है कि वर्ग उस तरह की कार्यक्षमता का समर्थन करता है। आप इस तरह की विधि को आसानी से लागू कर सकते हैं:

def to_dict(self):
    class_vars = vars(MyClass)  # get any "default" attrs defined at the class level
    inst_vars = vars(self)  # get any attrs defined on the instance (self)
    all_vars = dict(class_vars)
    all_vars.update(inst_vars)
    # filter out private attributes
    public_vars = {k: v for k, v in all_vars.items() if not k.startswith('_')}
    return public_vars

1

समस्या के पूरे संदर्भ को जाने बिना कहना मुश्किल है, लेकिन मैं ओवरराइड नहीं करूंगा __iter__।

मैं __what_goes_here__वर्ग पर लागू होता ।

as_dict(self:
    d = {...whatever you need...}
    return d

नहीं, कि चर में क्या संग्रहित किया जाता है।
— Zizouz212

3
मैंने विशेष रूप से बताया कि मुझे जो चाहिए w.__dict__वह नहीं करता है।
— लगन

लेकिन __dict__ओवरराइड हो सकता है, क्या ऐसा नहीं हो सकता?
— noisewaterphd

@noisewaterphd नहीं यह एक जादू की विधि है (हो सकता है कि आप इसे ओवरराइड कर सकते हैं, लेकिन इसमें निहितार्थ कम से कम कहने के लिए डरावने हैं)
— Joran Beasley

1
तानाशाह से विरासत में क्यों नहीं, या शायद अभी तक बेहतर है, बस इसे एक तानाशाह के रूप में लौटाने के लिए कक्षा में एक विधि बनाएं।
— noisewaterphd

0

मैं एक वर्ग लिखने की कोशिश कर रहा हूं जो "ए" listया ए है dict। मैं चाहता हूं कि प्रोग्रामर इस ऑब्जेक्ट को "कास्ट" list(कुंजी छोड़ने) या dict(कुंजियों के साथ ) दोनों में सक्षम हो ।

वर्तमान में पायथन जिस तरह से dict()कलाकारों को करता है उसे देखते हुए: यह Mapping.update()उस ऑब्जेक्ट के साथ कॉल करता है जो पारित हो जाता है। यह पायथन रेपो का कोड है :

def update(self, other=(), /, **kwds):
    ''' D.update([E, ]**F) -> None.  Update D from mapping/iterable E and F.
        If E present and has a .keys() method, does:     for k in E: D[k] = E[k]
        If E present and lacks .keys() method, does:     for (k, v) in E: D[k] = v
        In either case, this is followed by: for k, v in F.items(): D[k] = v
    '''
    if isinstance(other, Mapping):
        for key in other:
            self[key] = other[key]
    elif hasattr(other, "keys"):
        for key in other.keys():
            self[key] = other[key]
    else:
        for key, value in other:
            self[key] = value
    for key, value in kwds.items():
        self[key] = value

इफ स्टेटमेंट का अंतिम उप-भाग, जहां यह अधिक otherसे अधिक लोगों को ध्यान में रखता है। हालांकि, जैसा कि आप देख सकते हैं, एक keys()संपत्ति होना भी संभव है । कि, __getitem__()एक उप के साथ मिलकर एक उपवर्ग को ठीक से एक शब्दकोश में डालना आसान बना देना चाहिए:

class Wharrgarbl(object):
    def __init__(self, a, b, c, sum, version='old'):
        self.a = a
        self.b = b
        self.c = c
        self.sum = 6
        self.version = version

    def __int__(self):
        return self.sum + 9000

    def __keys__(self):
        return ["a", "b", "c"]

    def __getitem__(self, key):
        # have obj["a"] -> obj.a
        return self.__getattribute__(key)

तब यह काम करेगा:

>>> w = Wharrgarbl('one', 'two', 'three', 6)
>>> dict(w)
{'a': 'one', 'c': 'three', 'b': 'two'}

आपने मैपिंग प्रोटोकॉल लागू किया है। ऊपर मेरे उत्तर में विकल्प 3 देखें । यदि आप भी listड्रॉपिंग कीज़ बनाना चाहते हैं , तो आप एक ऐसा __iter__तरीका जोड़ सकते हैं जो मानों के माध्यम से पुनरावृत्ति करता है, और कास्टिंग dictअभी भी काम करना जारी रखेगा। ध्यान दें कि आम तौर पर शब्दकोशों के साथ, यदि आप किसी सूची में जाते हैं, तो यह कुंजी को वापस दे देगा, और मूल्यों की आवश्यकता नहीं है। यह आपके कोड का उपयोग करने वाले अन्य लोगों के लिए आश्चर्यजनक हो सकता है जब तक कि यह स्पष्ट नहीं है कि ऐसा क्यों होगा।
— रिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.