डॉट का उपयोग कैसे करें " शब्दकोश के सदस्यों का उपयोग करने के लिए?


282

मैं पायथन शब्दकोश के सदस्यों को एक डॉट "" के माध्यम से कैसे सुलभ कर सकता हूं? "

उदाहरण के लिए, लिखने के बजाय mydict['val'], मैं लिखना चाहूंगा mydict.val

इसके अलावा, मैं इस तरह से नेस्टेड डिक्सेस एक्सेस करना चाहूंगा। उदाहरण के लिए

mydict.mydict2.val 

को संदर्भित करेगा

mydict = { 'mydict2': { 'val': ... } }

20
कई स्थितियों में जहां लोग नेस्टेड डाइक का उपयोग करते हैं, उतने ही अच्छे या बेहतर तरीके से टिक्ल्स के साथ चाबी के रूप में परोसा जाता है, जहां d[a][b][c]से प्रतिस्थापित किया जाता है d[a, b, c]
माइक ग्राहम

7
यह जादू नहीं है: फू = {}; foo [1,2,3] = "एक, दो, तीन!"; foo.keys () => [(1,2,3)]
ब्रायन ओकले

10
वाह। फिर से वाह। मुझे नहीं पता था कि टुपल्स तानाशाह की चाबी हो सकते हैं। तीसरी बार वाह।
bodacydo

3
कोई भी वस्तु जो "हैशटैग" है, उसे एक तानाशाह की कुंजी के रूप में इस्तेमाल किया जा सकता है। अधिकांश अपरिवर्तनीय वस्तुएं भी धोने योग्य होती हैं, लेकिन केवल अगर उनकी सभी सामग्री धोने योग्य होती हैं। कोड d [1, 2, 3] काम करता है क्योंकि "," "एक टपल ऑपरेटर बनाएं"; यह d (1, 2, 3)] के समान है। कोहरे की घोषणा के आसपास कोष्ठक अक्सर वैकल्पिक होते हैं।
लैरी हेस्टिंग्स 3

6
क्या आपने उस मामले पर विचार किया है जहाँ कुंजी में एक बिंदु अपने आप है - {"my.key":"value"}? या जब कुंजी एक कीवर्ड है, जैसे "से"? मैंने इसे कई बार माना है, और यह कथित लाभों की तुलना में अधिक समस्याएं और समस्या निवारण है।
टोडर मिनाकोव

जवाबों:


147

आप इसे इस वर्ग का उपयोग कर सकते हैं जिसे मैंने अभी बनाया है। इस वर्ग के साथ आप Mapऑब्जेक्ट को दूसरे शब्दकोश (json serialization सहित) या डॉट नोटेशन के साथ उपयोग कर सकते हैं । मुझे आपकी मदद करने की उम्मीद है:

class Map(dict):
    """
    Example:
    m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
    """
    def __init__(self, *args, **kwargs):
        super(Map, self).__init__(*args, **kwargs)
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    self[k] = v

        if kwargs:
            for k, v in kwargs.iteritems():
                self[k] = v

    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(Map, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(Map, self).__delitem__(key)
        del self.__dict__[key]

उपयोग के उदाहरण:

m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
# Add new key
m.new_key = 'Hello world!'
# Or
m['new_key'] = 'Hello world!'
print m.new_key
print m['new_key']
# Update values
m.new_key = 'Yay!'
# Or
m['new_key'] = 'Yay!'
# Delete key
del m.new_key
# Or
del m['new_key']

21
Python 3 पर काम करने के लिए मैंने .iteritems().items()
बजे

13
ध्यान दें कि यह सामान्य अपेक्षाओं से अलग व्यवहार करेगा कि यह नहीं बढ़ेगा AttributeErrorयदि विशेषता मौजूद नहीं है। इसके बजाय यह वापस आ जाएगी None
mic_e

गेटस्टेट और सेटस्टेट जोड़ने की सलाह दें ताकि गहरी प्रतिलिपि और अन्य प्रणालियाँ इसका समर्थन कर सकें।
user1363990

4
आप अपने कंस्ट्रक्टर को सरल बना सकते हैं self.update(*args,**kwargs)। इसके अलावा, आप जोड़ सकते हैं __missing__(self,key): value=self[key]= type(self)(); return value। फिर आप डॉट नोटेशन का उपयोग करके लापता प्रविष्टियों को जोड़ सकते हैं। यदि आप चाहते हैं कि यह योग्य हो, तो आप जोड़ सकते हैं __getstate__और__setstate__
जेन्स

1
इससे hasattr(Map, 'anystring') is true. which means the hasattr would always return True due to overriding __getattr__`
Xiao

264

मैंने हमेशा इसे एक उपयोग फ़ाइल में रखा है। आप इसे मिक्सिन के रूप में अपनी कक्षाओं में भी इस्तेमाल कर सकते हैं।

class dotdict(dict):
    """dot.notation access to dictionary attributes"""
    __getattr__ = dict.get
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

mydict = {'val':'it works'}
nested_dict = {'val':'nested works too'}
mydict = dotdict(mydict)
mydict.val
# 'it works'

mydict.nested = dotdict(nested_dict)
mydict.nested.val
# 'nested works too'

5
बहुत सरल उत्तर, बहुत बढ़िया! क्या आपको पता है कि आईपीथॉन के काम को पूरा करने के लिए मुझे क्या करना होगा? वर्ग को __dir __ (स्वयं) को लागू करने की आवश्यकता होगी, लेकिन किसी तरह मुझे यह काम करने के लिए नहीं मिल सकता है।
andreas-h

8
सादगी के लिए +1। लेकिन नेस्टेड डाइक पर काम नहीं करता है। d = {'foo': {'bar': 'baz'}}; d = dotdict(d); d.foo.barएक विशेषता त्रुटि फेंकता है, लेकिन d.fooठीक काम करता है।
tmthyjames

2
हां, यह जटिल नेस्टेड संरचनाओं के लिए काम नहीं करता है।
डेविड

16
@tmthyjames आप केवल डॉट नोटेशन के साथ पुनरावर्ती अभिगम विशेषताओं के लिए गेटर विधि में डॉटडिक्ट टाइप ऑब्जेक्ट वापस कर सकते हैं जैसे: python class DotDict(dict): """dot.notation access to dictionary attributes""" def __getattr__(*args): val = dict.get(*args) return DotDict(val) if type(val) is dict else val __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__
TMKasun

4
इसके साथ प्रयोग करने के बाद, यह getवास्तव में एक बुरा विचार है क्योंकि यह Noneलापता वस्तुओं के लिए एक त्रुटि को बढ़ाने के बजाय वापस आ जाएगा ...
NichtJens

117

के dotmapमाध्यम से स्थापित करेंpip

pip install dotmap

यह वह सब कुछ करता है जो आप इसे करना चाहते हैं और उपवर्ग करते हैं dict, इसलिए यह एक सामान्य शब्दकोश की तरह संचालित होता है:

from dotmap import DotMap

m = DotMap()
m.hello = 'world'
m.hello
m.hello += '!'
# m.hello and m['hello'] now both return 'world!'
m.val = 5
m.val2 = 'Sam'

उसके ऊपर, आप इसे dictऑब्जेक्ट्स से और इसमें कनवर्ट कर सकते हैं:

d = m.toDict()
m = DotMap(d) # automatic conversion in constructor

इसका मतलब है कि अगर आप जिस चीज को एक्सेस करना चाहते हैं dict, वह पहले से ही फॉर्म में है, तो आप इसे DotMapआसान एक्सेस के लिए बदल सकते हैं :

import json
jsonDict = json.loads(text)
data = DotMap(jsonDict)
print data.location.city

अंत में, यह स्वचालित रूप से नए बच्चे DotMapउदाहरण बनाता है ताकि आप इस तरह की चीजें कर सकें:

m = DotMap()
m.people.steve.age = 31

बंच की तुलना

पूर्ण प्रकटीकरण: मैं डॉटपॉट का निर्माता हूं । मैंने इसे बनाया क्योंकि Bunchये सुविधाएँ गायब थीं

  • याद रहे ऑर्डर आइटम जोड़े जाते हैं और उस क्रम में पुनरावृति होती है
  • स्वचालित बाल DotMapनिर्माण, जो बहुत पदानुक्रम होने पर क्लीनर कोड के लिए समय बचाता है और बनाता है
  • एक से निर्माण dictऔर पुनरावर्ती सभी बच्चे के dictउदाहरणों में परिवर्तित करनाDotMap

2
:-) क्या आप इसे उन कुंजियों के साथ काम कर सकते हैं जो पहले से ही नाम में डॉट हैं? {"test.foo": "bar"}के माध्यम से पहुँचा जा सकता है mymap.test.fooकि शानदार होगा। एक फ्लैट के नक्शे को एक गहरे नक्शे में बदलने के लिए कुछ प्रतिगमन करना होगा, फिर उस पर DotMap लागू करें, लेकिन यह इसके लायक है!
dlite922

साफ। जुपिटर नोटबुक में कुंजियों के साथ टैब लिस्टिंग / पूर्ण कार्य करने का कोई तरीका? इंटरैक्टिव उपयोग के लिए डॉट-शैली की पहुंच सबसे मूल्यवान है।
दिमित्री

@ डमित्री कूल उत्पाद। पहले कभी इसके बारे में नहीं सुना, इसलिए मुझे यकीन नहीं है कि इसका स्वत: पूर्ण काम कैसे किया जाए। मैं DotMapस्वतः पूर्ण कार्यों के साथ उपयोग करने के लिए सहमत हूं । मैं उदात्त पाठ का उपयोग करता हूं, जो पहले टाइप किए गए कीवर्ड को स्वतः पूर्ण करता है।
क्रिस रेडफोर्ड

1
मुझे लगता है कि यह जैसी चीजों के लिए शब्दकोश निष्कर्षण का अभाव है **kwargsया c = {**a, **b}। वास्तव में, यह चुपचाप विफल रहता है, निकालने पर यह एक खाली शब्दकोश की तरह व्यवहार करता है।
साइमन स्ट्रेचर

@SimonStreicher मैंने इसके साथ परीक्षण किया m = DotMap(); m.a = 2; m.b = 3; print('{a} {b}'.format(**m));और मुझे उम्मीद थी 2 3। यदि आपके पास एक सिद्ध टूटा हुआ मामला है जो काम करता है dict()लेकिन नहीं DotMap(), तो कृपया अपना कोड GitHub में जारी करने वाले टैब पर जमा करें।
क्रिस रेडफोर्ड

56

तानाशाही से मुक्ति और लागू __getattr__और __setattr__

या आप बंच का उपयोग कर सकते हैं जो बहुत समान है।

मुझे नहीं लगता कि बिल्ट-इन तानाशाह वर्ग के लिए यह संभव है।


2
मंकीपैच का वास्तव में क्या मतलब है? मैंने इसके बारे में सुना है लेकिन इसका इस्तेमाल नहीं किया है। (क्षमा करें कि मैं इस तरह के नौसिखिया सवाल पूछता हूं, मैं प्रोग्रामिंग के साथ अभी तक अच्छा नहीं हूं (मैं केवल द्वितीय वर्ष का छात्र हूं।))
bodacydo

9
मंकीपॉचिंग पायथन (या जो भी भाषा) की गतिशीलता का उपयोग करके कुछ को बदलने के लिए किया जाता है जिसे आमतौर पर स्रोत कोड में परिभाषित किया जाएगा। यह विशेष रूप से वर्गों के बनने के बाद उनकी परिभाषा बदलने पर लागू होता है।
माइक ग्राहम

यदि आप इस कार्यक्षमता का उपयोग कर रहे हैं, तो बंच की गति से सावधान रहें। मैं इसे बहुत बार उपयोग कर रहा था और यह मेरे अनुरोध समय के एक तिहाई का उपभोग कर रहा था। इस बारे में अधिक विस्तृत विवरण के लिए मेरे उत्तर की जाँच करें।
JayD3e

22

फैब्रिक में वास्तव में अच्छा, न्यूनतम कार्यान्वयन है । नेस्टेड एक्सेस की अनुमति देने के लिए, हम इसका उपयोग कर सकते हैं defaultdict, और परिणाम कुछ इस तरह दिखता है:

from collections import defaultdict

class AttributeDict(defaultdict):
    def __init__(self):
        super(AttributeDict, self).__init__(AttributeDict)

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError(key)

    def __setattr__(self, key, value):
        self[key] = value

इसे निम्नानुसार उपयोग करें:

keys = AttributeDict()
keys.abc.xyz.x = 123
keys.abc.xyz.a.b.c = 234

यह कुगेल के "तानाशाही से__getattr____setattr__ मुक्ति और लागू करने और " के जवाब पर थोड़ा विस्तार करता है अब आप जानते हैं कि कैसे!


1
वह एक कमाल है!
थॉमस क्लिंगर

एक डिफ़ॉल्ट शामिल करने के लिए अच्छा है - हालांकि यह केवल खरोंच से एक तानाशाही शुरू करने पर काम करता है। अगर हमें मौजूदा तानाशाही को एक "डॉटडिक्ट" के रूप में पुनरावृत्ति करने की आवश्यकता है। यहाँ एक विकल्प है dotdictजो मौजूदा रूपांतरित करने की अनुमति dict: वस्तु रिकर्सिवली gist.github.com/miku/...
Miku

19

मैंने यह कोशिश की:

class dotdict(dict):
    def __getattr__(self, name):
        return self[name]

आप भी कोशिश कर सकते __getattribute__हैं।

हर हुकुम को एक प्रकार का फैसला करना काफी अच्छा होगा, अगर आप इसे मल्टी-लेयर डिक्टेट से चाहते हैं, तो इसे लागू करने का __init__भी प्रयास करें ।


उफ़, @Kugel का उत्तर समान है।
tadihp

1
tdihp, मुझे आपका उत्तर अभी भी पसंद है क्योंकि मैंने इसे तेजी से समझा - इसका वास्तविक कोड है।
यिगाल

1
वास्तविक कोड के लिए +1। लेकिन @ कुंगेल का बंच इस्तेमाल करने का सुझाव भी बहुत अच्छा है।
Dannid

मैंने इसे एक फ़ंक्शन के अंदर एम्बेड करने def docdict(name):से पहले इसे उपयोगी पाया और फिर `अगर आइंस्टीन (नाम, तानाशाह): रिटर्न डॉटडिक्ट (नाम) वापसी
नाम`

महान सरल उदाहरण है .. मैं इस एक छोटे से इतना सा है कि एक नेस्टेड dict आसानी से श्रृंखलित है @DanielMoskovich के समान बढ़ाया, लेकिन यह भी पूर्णांक, स्ट्रिंग, आदि ... या नल के लिए सही ढंग से पत्र-गांठ लौटाता है यदि नहीं मिलाclass dotdict(dict): def __getattr__(self, name): if name not in self: return None elif type(self[name]) is dict: return JsonDot(self[name]) else: return self[name]
डी सिवर्स

11

मत करो। पायथन में पहुंच और अनुक्रमण को अलग-अलग चीजें हैं, और आप नहीं चाहते कि वे समान प्रदर्शन करें। namedtupleयदि आपके पास ऐसी कोई चीज है, जिसमें सुलभ गुण होना चाहिए और []किसी तानाशाह से वस्तु प्राप्त करने के लिए अंकन का उपयोग करना चाहिए, तो एक कक्षा बनाएं (संभवतः एक के बाद एक ) ।


जवाब के लिए धन्यवाद। लेकिन इस सवाल पर एक नज़र डालें, जो मैंने अभी भी पूछा: stackoverflow.com/questions/2352252/… यह Mako टेम्पलेट्स में जटिल डेटा संरचनाओं .का उपयोग करने के बजाय उपयोग करने के []लिए एक अच्छा विचार है ।
बॉडासिडो

2
मैं इसके लिए एक उपयोग मामला देख सकता हूं; वास्तव में, मैंने इसे कुछ हफ़्ते पहले किया था। मेरे मामले में मुझे एक वस्तु चाहिए थी जिसे मैं डॉट नोटेशन के साथ विशेषताओं तक पहुंच सकता हूं। मुझे यह बहुत आसान लगा कि मुझे केवल तानाशाही से विरासत में प्राप्त करना है, इसलिए मुझे अंतर्निहित सभी तानाशाह सुविधाएँ मिलती हैं, लेकिन इस ऑब्जेक्ट के लिए सार्वजनिक इंटरफ़ेस डॉट नोटेशन का उपयोग करता है (यह अनिवार्य रूप से कुछ स्थिर डेटा के लिए केवल-पढ़ने के लिए इंटरफ़ेस है)। मेरे उपयोगकर्ता "foo.bar’ के साथ [foo [”बार”] की तुलना में अधिक खुश हैं और मुझे खुशी है कि मैं डिक्टेटप्रकट की विशेषताओं से पीछे हट सकता हूं।
ब्रायन ओकले

10
आप पहले से ही अच्छे पायथन शैली को जानते हैं: हम आपको बता रहे हैं, इस बात का ढोंग न करें कि एक तानाशाह के मूल्य विशेषता हैं। यह बुरा अभ्यास है। उदाहरण के लिए, क्या होगा यदि आप "आइटम" या "प्राप्त करें" या "पॉप" जैसे एक तानाशाह की मौजूदा विशेषता के समान नाम के साथ एक मूल्य संग्रहीत करना चाहते हैं? शायद कुछ गड़बड़ है। तो यह मत करो!
लैरी हेस्टिंग्स 3

5
उफ़, मैं 'आइटम', 'गेट' या 'पॉप' जैसी विशेषताओं के बारे में भूल गया। इस महत्वपूर्ण उदाहरण को लाने के लिए धन्यवाद!
बोदासाइडो

5
@Gabe, यह एक लंबा समय रहा है ... लेकिन मुझे लगता है कि यह कहने लायक है। यह "जेएस में पर्याप्त अच्छा नहीं है": यह "जेएस में काफी भयानक" है। जब आप कुंजियाँ / पोशाक संग्रहीत करते हैं तो यह मज़ेदार हो जाता है, जिसका नाम प्रोटोटाइप श्रृंखला में अन्य महत्वपूर्ण विशेषताओं के समान होता है।
bgusach

11

यदि आप अपना संशोधित शब्दकोश चुनना चाहते हैं, तो आपको ऊपर दिए गए उत्तरों में कुछ राज्य विधियों को जोड़ना होगा:

class DotDict(dict):
    """dot.notation access to dictionary attributes"""
    def __getattr__(self, attr):
        return self.get(attr)
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

    def __getstate__(self):
        return self

    def __setstate__(self, state):
        self.update(state)
        self.__dict__ = self

अचार के बारे में टिप्पणी के लिए धन्यवाद। मैं इस त्रुटि से पागल हो गया था और केवल महसूस किया कि यह इस मुद्दे की वजह से था!
Shagru

जब आप copy.deepcopy का उपयोग करते हैं, तब भी होता है। इस जोड़ की जरूरत है।
user1363990

सरलीकरण:__getattr__ = dict.get
मार्टीन्यू

9

कुगेल के जवाब पर निर्माण करना और माइक ग्राहम की सावधानी के शब्दों को ध्यान में रखना, अगर हम एक आवरण बनाते हैं तो क्या होगा?

class DictWrap(object):
  """ Wrap an existing dict, or create a new one, and access with either dot 
    notation or key lookup.

    The attribute _data is reserved and stores the underlying dictionary.
    When using the += operator with create=True, the empty nested dict is 
    replaced with the operand, effectively creating a default dictionary
    of mixed types.

    args:
      d({}): Existing dict to wrap, an empty dict is created by default
      create(True): Create an empty, nested dict instead of raising a KeyError

    example:
      >>>dw = DictWrap({'pp':3})
      >>>dw.a.b += 2
      >>>dw.a.b += 2
      >>>dw.a['c'] += 'Hello'
      >>>dw.a['c'] += ' World'
      >>>dw.a.d
      >>>print dw._data
      {'a': {'c': 'Hello World', 'b': 4, 'd': {}}, 'pp': 3}

  """

  def __init__(self, d=None, create=True):
    if d is None:
      d = {}
    supr = super(DictWrap, self)  
    supr.__setattr__('_data', d)
    supr.__setattr__('__create', create)

  def __getattr__(self, name):
    try:
      value = self._data[name]
    except KeyError:
      if not super(DictWrap, self).__getattribute__('__create'):
        raise
      value = {}
      self._data[name] = value

    if hasattr(value, 'items'):
      create = super(DictWrap, self).__getattribute__('__create')
      return DictWrap(value, create)
    return value

  def __setattr__(self, name, value):
    self._data[name] = value  

  def __getitem__(self, key):
    try:
      value = self._data[key]
    except KeyError:
      if not super(DictWrap, self).__getattribute__('__create'):
        raise
      value = {}
      self._data[key] = value

    if hasattr(value, 'items'):
      create = super(DictWrap, self).__getattribute__('__create')
      return DictWrap(value, create)
    return value

  def __setitem__(self, key, value):
    self._data[key] = value

  def __iadd__(self, other):
    if self._data:
      raise TypeError("A Nested dict will only be replaced if it's empty")
    else:
      return other

8

उपयोग करें SimpleNamespace:

>>> from types import SimpleNamespace   
>>> d = dict(x=[1, 2], y=['a', 'b'])
>>> ns = SimpleNamespace(**d)
>>> ns.x
[1, 2]
>>> ns
namespace(x=[1, 2], y=['a', 'b'])

1
यह दृष्टिकोण बेहतर काम करता है। (फ़ाइल से लोड किए गए json के साथ)
ged

क्या यह नेस्टेड डाइक्ट्स के लिए है?
मौजिमी

1
नेस्टेड डिक्ट का समर्थन नहीं करते। docs.python.org/3.3/library/types.html#types.SimpleNamespace
कार्सन

6

मुझे चबाना पसंद है और यह डॉट एक्सेस के शीर्ष पर बहुत सारे विकल्प देता है।

आयात चबाना

temp_1 = {'person': {'fname': 'senthil', 'lname': 'ramalinga'}}

तानाशाह_मंच = चबाना। (temp_1)

dict_munch.person.fname


6

मैं हाल ही में ' बॉक्स ' लाइब्रेरी में आया था जो यही काम करता है।

स्थापना आदेश: pip install python-box

उदाहरण:

from box import Box

mydict = {"key1":{"v1":0.375,
                    "v2":0.625},
          "key2":0.125,
          }
mydict = Box(mydict)

print(mydict.key1.v1)

मुझे यह अन्य मौजूदा पुस्तकालयों की तुलना में अधिक प्रभावी लगा, जैसे कि डॉटमैप, जो बड़े नेस्टेड डाइक होने पर पायथन रिकर्सन एरर उत्पन्न करते हैं।

पुस्तकालय और विवरण के लिए लिंक: https://pypi.org/project/python-box/


5

उपयोग __getattr__, बहुत ही सरल, पायथन 3.4.3 में काम करता है

class myDict(dict):
    def __getattr__(self,val):
        return self[val]


blockBody=myDict()
blockBody['item1']=10000
blockBody['item2']="StackOverflow"
print(blockBody.item1)
print(blockBody.item2)

आउटपुट:

10000
StackOverflow

4

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

def get_var(input_dict, accessor_string):
    """Gets data from a dictionary using a dotted accessor-string"""
    current_data = input_dict
    for chunk in accessor_string.split('.'):
        current_data = current_data.get(chunk, {})
    return current_data

जो इस तरह से कुछ का समर्थन करेगा:

>> test_dict = {'thing': {'spam': 12, 'foo': {'cheeze': 'bar'}}}
>> output = get_var(test_dict, 'thing.spam.foo.cheeze')
>> print output
'bar'
>>

4

एपोल के उत्तर का निर्माण करने के लिए, यह संस्करण आपको डॉट ऑपरेटर के माध्यम से किसी भी हुक्म से अंदर पहुँचने की अनुमति देता है:

foo = {
    "bar" : {
        "baz" : [ {"boo" : "hoo"} , {"baba" : "loo"} ]
    }
}

मसलन, foo.bar.baz[1].babaरिटर्न "loo"

class Map(dict):
    def __init__(self, *args, **kwargs):
        super(Map, self).__init__(*args, **kwargs)
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    if isinstance(v, dict):
                        v = Map(v)
                    if isinstance(v, list):
                        self.__convert(v)
                    self[k] = v

        if kwargs:
            for k, v in kwargs.iteritems():
                if isinstance(v, dict):
                    v = Map(v)
                elif isinstance(v, list):
                    self.__convert(v)
                self[k] = v

    def __convert(self, v):
        for elem in xrange(0, len(v)):
            if isinstance(v[elem], dict):
                v[elem] = Map(v[elem])
            elif isinstance(v[elem], list):
                self.__convert(v[elem])

    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(Map, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(Map, self).__delitem__(key)
        del self.__dict__[key]

1
अजगर 3: की जगह iteritems()के साथ items()और xrange()साथrange()
sasawatc

3
def dict_to_object(dick):
    # http://stackoverflow.com/a/1305663/968442

    class Struct:
        def __init__(self, **entries):
            self.__dict__.update(entries)

    return Struct(**dick)

यदि कोई व्यक्ति इसे करने के लिए स्थायी रूप से परिवर्तित करने का निर्णय करता है, dictतो उसे ऐसा करना चाहिए। आप पहुंचने से ठीक पहले एक फालतू वस्तु बना सकते हैं।

d = dict_to_object(d)

def attr (** kwargs): o = lambda: कोई नहीं o .__ तानाशाही __। update (** kwargs) वापसी o
throws_exception_at_you

2

मैंने बीओटीएच एट्रेडिट की कोशिश की और बंच कीपुस्तकालयों और उन्हें मेरे उपयोग के लिए धीमा करने का तरीका मिला। एक दोस्त के बाद और मैंने इस पर गौर किया, हमने पाया कि इन पुस्तकालयों को लिखने का मुख्य तरीका पुस्तकालय में आक्रामक रूप से एक नेस्टेड ऑब्जेक्ट के माध्यम से पुनरावृत्ति करना और पूरे शब्दकोश ऑब्जेक्ट की प्रतियां बनाना है। इसे ध्यान में रखते हुए, हमने दो महत्वपूर्ण बदलाव किए। 1) हमने विशेषताओं को आलसी लोड किया 2) एक शब्दकोश वस्तु की प्रतियां बनाने के बजाय, हम एक हल्के वजन वाली प्रॉक्सी वस्तु की प्रतियां बनाते हैं। यह अंतिम कार्यान्वयन है। इस कोड का उपयोग करने की प्रदर्शन वृद्धि अविश्वसनीय है। AttrDict या Bunch का उपयोग करते समय, इन दोनों पुस्तकालयों ने मेरे अनुरोध समय के क्रमशः 1/2 और 1/3 का उपभोग किया (क्या !?)। इस कोड ने उस समय को लगभग कुछ भी नहीं (कहीं न कहीं 0.5ms की सीमा में) घटा दिया। यह पाठ्यक्रम आपकी आवश्यकताओं पर निर्भर करता है, लेकिन यदि आप इस कार्यक्षमता का उपयोग अपने कोड में बहुत कम कर रहे हैं,

class DictProxy(object):
    def __init__(self, obj):
        self.obj = obj

    def __getitem__(self, key):
        return wrap(self.obj[key])

    def __getattr__(self, key):
        try:
            return wrap(getattr(self.obj, key))
        except AttributeError:
            try:
                return self[key]
            except KeyError:
                raise AttributeError(key)

    # you probably also want to proxy important list properties along like
    # items(), iteritems() and __len__

class ListProxy(object):
    def __init__(self, obj):
        self.obj = obj

    def __getitem__(self, key):
        return wrap(self.obj[key])

    # you probably also want to proxy important list properties along like
    # __iter__ and __len__

def wrap(value):
    if isinstance(value, dict):
        return DictProxy(value)
    if isinstance(value, (tuple, list)):
        return ListProxy(value)
    return value

मूल कार्यान्वयन यहाँ देखें https://stackoverflow.com/users/704327/michael-merickel द्वारा ।

ध्यान देने वाली दूसरी बात यह है कि यह कार्यान्वयन बहुत सरल है और उन सभी तरीकों को लागू नहीं करता है जिनकी आपको आवश्यकता हो सकती है। आपको DictProxy या ListProxy ऑब्जेक्ट पर आवश्यकतानुसार लिखना होगा।


0

मैं रिंग में अपना खुद का समाधान फेंकना चाहता हूं:

https://github.com/skorokithakis/jsane

यह आपको उस JSON को पार्स करने की अनुमति देता है जिसे आप एक्सेस कर सकते हैं with.attribute.lookups.like.this.r(), ज्यादातर क्योंकि मैंने इस पर काम शुरू करने से पहले इस उत्तर को नहीं देखा था।


पायथन कुछ pesky सरल डिजाइन गलतियों के लिए दोषी है, उठाना KeyErrorउनमें से एक है, जब कोई उस कुंजी का उपयोग करता है जो मौजूद नहीं है, तो यह Noneजेएस व्यवहार के समान है। मैं पढ़ने और लिखने दोनों के लिए आत्मकथा का बहुत बड़ा प्रशंसक हूं। आपका पुस्तकालय आदर्श के सबसे करीब है।
नेहेम

0

ओपी के सवाल का सीधा जवाब नहीं है, लेकिन कुछ के लिए प्रेरित और शायद उपयोगी है। मैंने आंतरिक __dict__(कोई रास्ता नहीं अनुकूलित कोड) का उपयोग करके एक वस्तु-आधारित समाधान बनाया है

payload = {
    "name": "John",
    "location": {
        "lat": 53.12312312,
        "long": 43.21345112
    },
    "numbers": [
        {
            "role": "home",
            "number": "070-12345678"
        },
        {
            "role": "office",
            "number": "070-12345679"
        }
    ]
}


class Map(object):
    """
    Dot style access to object members, access raw values
    with an underscore e.g.

    class Foo(Map):
        def foo(self):
            return self.get('foo') + 'bar'

    obj = Foo(**{'foo': 'foo'})

    obj.foo => 'foobar'
    obj._foo => 'foo'

    """

    def __init__(self, *args, **kwargs):
        for arg in args:
            if isinstance(arg, dict):
                for k, v in arg.iteritems():
                    self.__dict__[k] = v
                    self.__dict__['_' + k] = v

        if kwargs:
            for k, v in kwargs.iteritems():
                self.__dict__[k] = v
                self.__dict__['_' + k] = v

    def __getattribute__(self, attr):
        if hasattr(self, 'get_' + attr):
            return object.__getattribute__(self, 'get_' + attr)()
        else:
            return object.__getattribute__(self, attr)

    def get(self, key):
        try:
            return self.__dict__.get('get_' + key)()
        except (AttributeError, TypeError):
            return self.__dict__.get(key)

    def __repr__(self):
        return u"<{name} object>".format(
            name=self.__class__.__name__
        )


class Number(Map):
    def get_role(self):
        return self.get('role')

    def get_number(self):
        return self.get('number')


class Location(Map):
    def get_latitude(self):
        return self.get('lat') + 1

    def get_longitude(self):
        return self.get('long') + 1


class Item(Map):
    def get_name(self):
        return self.get('name') + " Doe"

    def get_location(self):
        return Location(**self.get('location'))

    def get_numbers(self):
        return [Number(**n) for n in self.get('numbers')]


# Tests

obj = Item({'foo': 'bar'}, **payload)

assert type(obj) == Item
assert obj._name == "John"
assert obj.name == "John Doe"
assert type(obj.location) == Location
assert obj.location._lat == 53.12312312
assert obj.location._long == 43.21345112
assert obj.location.latitude == 54.12312312
assert obj.location.longitude == 44.21345112

for n in obj.numbers:
    assert type(n) == Number
    if n.role == 'home':
        assert n.number == "070-12345678"
    if n.role == 'office':
        assert n.number == "070-12345679"

0

डॉट एक्सेस प्राप्त करने का एक सरल तरीका (लेकिन एरे एक्सेस नहीं है), पायथन में एक सादे ऑब्जेक्ट का उपयोग करना है। ऐशे ही:

class YourObject:
    def __init__(self, *args, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

... और इसे इस तरह उपयोग करें:

>>> obj = YourObject(key="value")
>>> print(obj.key)
"value"

... इसे एक हुकुम में बदलने के लिए:

>>> print(obj.__dict__)
{"key": "value"}

0

यह समाधान ओपूल द्वारा प्रस्तावित नेस्टेड डक्ट्स को सुसंगत तरीके से उपयोग करने के लिए संबोधित करने की पेशकश पर एक शोधन है। एपोल द्वारा समाधान नेस्टेड डक्ट्स तक पहुंचने की अनुमति नहीं दी।

class YAMLobj(dict):
    def __init__(self, args):
        super(YAMLobj, self).__init__(args)
        if isinstance(args, dict):
            for k, v in args.iteritems():
                if not isinstance(v, dict):
                    self[k] = v
                else:
                    self.__setattr__(k, YAMLobj(v))


    def __getattr__(self, attr):
        return self.get(attr)

    def __setattr__(self, key, value):
        self.__setitem__(key, value)

    def __setitem__(self, key, value):
        super(YAMLobj, self).__setitem__(key, value)
        self.__dict__.update({key: value})

    def __delattr__(self, item):
        self.__delitem__(item)

    def __delitem__(self, key):
        super(YAMLobj, self).__delitem__(key)
        del self.__dict__[key]

इस वर्ग के साथ, एक अब की तरह कुछ कर सकते हैं: A.B.C.D


0

यह नेस्टेड डाइक के साथ भी काम करता है और यह सुनिश्चित करता है कि बाद में अप्वाइंट किए गए डक्ट्स समान व्यवहार करें:

class DotDict(dict):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Recursively turn nested dicts into DotDicts
        for key, value in self.items():
            if type(value) is dict:
                self[key] = DotDict(value)

    def __setitem__(self, key, item):
        if type(item) is dict:
            item = DotDict(item)
        super().__setitem__(key, item)

    __setattr__ = __setitem__
    __getattr__ = dict.__getitem__

0

@ Derek73 का उत्तर बहुत साफ है, लेकिन इसे कॉपी नहीं किया जा सकता है और न ही (गहरी) नकल की जा सकती है, और यह Noneलापता कुंजी के लिए वापस आ जाती है। नीचे दिया गया कोड इसे ठीक करता है।

संपादित करें: मैंने ऊपर दिए गए उत्तर को नहीं देखा जो सटीक एक ही बिंदु (उत्कीर्ण) को संबोधित करता है। मैं यहाँ संदर्भ के लिए उत्तर छोड़ रहा हूँ।

class dotdict(dict):
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            raise AttributeError(name)

-1

एक प्रकार का नाजुक

class DotDict(dict):

    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

    def __getattr__(self, key):

        def typer(candidate):
            if isinstance(candidate, dict):
                return DotDict(candidate)

            if isinstance(candidate, str):  # iterable but no need to iter
                return candidate

            try:  # other iterable are processed as list
                return [typer(item) for item in candidate]
            except TypeError:
                return candidate

            return candidate

        return typer(dict.get(self, key))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.