2012-04-05 10 views
8

में विशेषताओं के रूप में JSON कुंजी का उपयोग करके मैं अजगर जेएसओएन जैसी डेटा संरचनाओं के साथ काम कर रहा हूं 2.7 कि मैं कुछ विदेशी पर्ल कोड के साथ आदान-प्रदान करता हूं। मैं सिर्फ अमोर पायथनिक तरीके से सूचियों और शब्दकोशों के इन नेस्टेड संरचनाओं के साथ 'काम करना' चाहता हूं।नेस्टेड JSON

तो अगर मैं इस तरह एक संरचना ...

a = { 
    'x': 4, 
    'y': [2, 3, { 'a': 55, 'b': 66 }], 
} 

है ... मैं एक अजगर स्क्रिप्ट में इससे निपटने के लिए सक्षम होना चाहते हैं जैसे कि वह अजगर वर्गों/Structs, नेस्ट किया गया था इस तरह :

>>> aa = j2p(a) # <<- this is what I'm after. 
>>> print aa.x 
4 
>>> aa.z = 99 
>>> print a 
{ 
    'x': 4, 
    'y': [2, 3, { 'a': 55, 'b': 66 }], 
    'z': 99 
} 

>>> aa.y[2].b = 999 

>>> print a 
{ 
    'x': 4, 
    'y': [2, 3, { 'a': 55, 'b': 999 }], 
    'z': 99 
} 

इस प्रकार मूल संरचना में प्रॉक्सी है। यह मैं अब तक आया हूं, उत्कृष्ट What is a metaclass in Python? प्रश्न से प्रेरित है।

def j2p(x): 
    """j2p creates a pythonic interface to nested arrays and 
    dictionaries, as returned by json readers. 

    >>> a = { 'x':[5,8], 'y':5} 
    >>> aa = j2p(a) 
    >>> aa.y=7 
    >>> print a 
    {'x': [5, 8], 'y':7} 
    >>> aa.x[1]=99 
    >>> print a 
    {'x': [5, 99], 'y':7} 

    >>> aa.x[0] = {'g':5, 'h':9} 
    >>> print a 
    {'x': [ {'g':5, 'h':9} , 99], 'y':7} 
    >>> print aa.x[0].g 
    5 
    """ 
    if isinstance(x, list): 
     return _list_proxy(x) 
    elif isinstance(x, dict): 
     return _dict_proxy(x) 
    else: 
     return x 

class _list_proxy(object): 
    def __init__(self, proxied_list): 
     object.__setattr__(self, 'data', proxied_list) 
    def __getitem__(self, a): 
     return j2p(object.__getattribute__(self, 'data').__getitem__(a)) 
    def __setitem__(self, a, v): 
     return object.__getattribute__(self, 'data').__setitem__(a, v) 


class _dict_proxy(_list_proxy): 
    def __init__(self, proxied_dict): 
     _list_proxy.__init__(self, proxied_dict) 
    def __getattribute__(self, a): 
     return j2p(object.__getattribute__(self, 'data').__getitem__(a)) 
    def __setattr__(self, a, v): 
     return object.__getattribute__(self, 'data').__setitem__(a, v) 


def p2j(x): 
    """p2j gives back the underlying json-ic json-ic nested 
    dictionary/list structure of an object or attribute created with 
    j2p. 
    """ 
    if isinstance(x, (_list_proxy, _dict_proxy)): 
     return object.__getattribute__(x, 'data') 
    else: 
     return x 

अब मुझे आश्चर्य है कि __*__ विशेष कार्य का पूरा सेट मानचित्रण की एक सुंदर तरीका है कि क्या वहाँ __iter__, __delitem__ की तरह? इसलिए मुझे p2j() का उपयोग करके चीजों को अनदेखा करने की आवश्यकता नहीं है या फिर अन्य पाइथनिक चीजें करने के लिए।

# today: 
for i in p2j(aa.y): 
    print i 
# would like to... 
for i in aa.y: 
    print i 
+0

मुझे लगता है कि आप इस के लिए देख रहे हैं समाधान - http://stackoverflow.com/questions/4984647/accessing-dict-keys-like-an-attribute-in-python#answer-14620633 – Yurik

उत्तर

3

वहाँ an attrdict library कि वास्तव में एक बहुत ही सुरक्षित तरीके से करता है है, लेकिन अगर आप चाहते हैं, एक त्वरित और गंदे (संभवतः लीक स्मृति) दृष्टिकोण this answer में दिया गया था:

class AttrDict(dict): 
    def __init__(self, *args, **kwargs): 
     super(AttrDict, self).__init__(*args, **kwargs) 
     self.__dict__ = self 

j = '{"y": [2, 3, {"a": 55, "b": 66}], "x": 4}' 
aa = json.loads(j, object_hook=AttrDict) 
11

मुझे लगता है कि आप इसे और अधिक जटिल बनाने की आवश्यकता है। अगर मैं तुम्हें सही ढंग से समझ, तुम सब करने की जरूरत है चाहिए यह है:

import json 

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

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

    def __delattr__(self, name): 
     del self[name] 

j = '{"y": [2, 3, {"a": 55, "b": 66}], "x": 4}' 

aa = json.loads(j, object_hook=Struct) 

for i in aa.y: 
    print(i) 

जब आप JSON लोड, object_hook पैरामीटर आप वस्तुओं है कि यह लोड करता है प्रक्रिया पूरी होने में प्रतिदेय वस्तु निर्दिष्ट कर सकते हैं। मैंने इसे केवल उस ऑब्जेक्ट में बदलने के लिए उपयोग किया है जो विशेषता को अपनी चाबियों तक पहुंच प्रदान करता है। Docs

+0

यह एक दिलचस्प दृष्टिकोण है। हालांकि ऐसा लगता है कि मैंने 'dict() 'संरचना के' सूची()' के अंतर्निहित नेस्टेड 'dict()' को खोला है, यह कभी भी निर्मित नहीं हुआ है। और मैं उस पर निर्भर करता हूं। –

+0

@SusanneOberhauser: मुझे पूरा यकीन नहीं है कि आपका क्या मतलब है। यह केवल 'स्ट्रक्चर()' की 'सूची()' की 'संरचना()' होगी। 'instinstance (aa, dict) 'अभी भी काम करना चाहिए, क्योंकि संरचना उपखंडों को निर्देश दिया जाता है, और यदि आप इसकी आवश्यकता हो तो भी आप' aa ['y'] 'नोटेशन का उपयोग कर सकते हैं। ऐसा लगता है कि उस पर कोड अनुकूलित करना आसान होगा। –

+0

मुझे एहसास हुआ कि यदि मैं 'dict' के बजाय' स्ट्रक्चर 'के रूप में नेस्टेड स्ट्रक्चर को जोड़ता हूं, तो मैं जो भी इरादा रखता हूं, उसके करीब आता हूं, जब तक कि 'dict' विशेषताओं और शब्दकोश विशेषताओं के बीच कोई नाम नहीं है। 'aa.items'' स्ट्रक्चर 'के लिए एक अंतर्निहित विधि है, लेकिन यह '_dict_proxy' के लिए dict में एक कुंजी है। इसलिए 'aa.copy = 44' उत्तरार्द्ध में लक्षित के रूप में काम करता है, लेकिन पूर्व में नहीं। मुझे लगता है कि मैं वास्तव में समझना चाहता हूं कि पाइथन मेटा प्रोग्रामिंग का उपयोग करके प्रॉक्सी ऑब्जेक्ट में सदस्य फ़ंक्शंस के पूरे सेट को कैसे मैप करना है। –

1

मुझे उत्तर मिला: There is intentionally no way to automatically map the special methods in python, using __getattribute__। तो मैं जो चाहता हूं उसे प्राप्त करने के लिए, मुझे __len__ जैसे सभी विशेष तरीकों को स्पष्ट रूप से परिभाषित करने की आवश्यकता है।

संबंधित मुद्दे