2011-07-27 5 views
3

私はget_profile(js)のような関数を書く方法を探していますが、すべての醜いtry/exceptsはありません。Python - jsonオブジェクトからデータを取得している間に何十回もtry/exceptブロックを避けるためのエレガントな方法はありますか?

jsonフィールドが存在しないことがあるため、各割り当てはtry/exceptにあります。私は[]などのいくつかのデフォルトを設定していますが、すべてをデフォルトにしたエレガントなソリューションに満足しています。そうすれば、全体的なコードをもっとうまく作成できます。 dictionaries

  • コードの

    def get_profile(js): 
        """ given a json object, return a dict of a subset of the data. 
         what are some cleaner/terser ways to implement this? 
    
         There will be many other get_foo(js), get_bar(js) functions which 
         need to do the same general type of thing. 
        """ 
    
        d = {} 
    
        try: 
         d['links'] = js['entry']['gd$feedLink'] 
        except: 
         d['links'] = [] 
    
        try: 
         d['statisitcs'] = js['entry']['yt$statistics'] 
        except: 
         d['statistics'] = {} 
    
        try: 
         d['published'] = js['entry']['published']['$t'] 
        except: 
         d['published'] = '' 
    
        try: 
         d['updated'] = js['entry']['updated']['$t'] 
        except: 
         d['updated'] = '' 
    
        try: 
         d['age'] = js['entry']['yt$age']['$t'] 
        except: 
         d['age'] = 0 
    
        try: 
         d['name'] = js['entry']['author'][0]['name']['$t'] 
        except: 
         d['name'] = '' 
    
        return d 
    
  • 答えて

    3

    のようなものを試してみてください...

    import time 
    
    def get_profile(js): 
        def cas(prev, el): 
         if hasattr(prev, "get") and prev: 
          return prev.get(el, prev) 
         return prev 
        def getget(default, *elements): 
         return reduce(cas, elements[1:], js.get(elements[0], default)) 
    
        d = {} 
        d['links'] = getget([], 'entry', 'gd$feedLink') 
        d['statistics'] = getget({}, 'entry', 'yt$statistics') 
        d['published'] = getget('', 'entry', 'published', '$t') 
        d['updated'] = getget('', 'entry', 'updated', '$t') 
        d['age'] = getget(0, 'entry', 'yt$age', '$t') 
        d['name'] = getget('', 'entry', 'author', 0, 'name' '$t') 
        return d 
    
    print get_profile({ 
        'entry':{ 
         'gd$feedLink':range(4), 
         'yt$statistics':{'foo':1, 'bar':2}, 
         'published':{ 
          "$t":time.strftime("%x %X"), 
         }, 
         'updated':{ 
          "$t":time.strftime("%x %X"), 
         }, 
         'yt$age':{ 
          "$t":"infinity years", 
         }, 
         'author':{0:{'name':{'$t':"I am a cow"}}}, 
        } 
    }) 
    

    私がいることを前提とすることは、信仰の飛躍のようなものですあなたはリストの代わりに0のキーを持つ辞書を持っていますが...あなたはそのアイデアを得ます。

    +0

    明示的なループを使って書かれた場合、getgetが読みやすくなるかもしれません。それ以外の場合は素晴らしいアイデアです。私はこれを 'getget( 'entry'、 'gd $ feedLink'、default = [])のように呼ぶ方が好きですが、いい考えです。 –

    +0

    これは素晴らしい解決策です。'[0]'があった場合は、実際には辞書ではないリストです。それは実際に私が探していたものです(そして、何年か前に書かれたこともありますが、現時点では手軽ではありません)。 –

    8
    1. 使用get(key[, default])方法この定型的なコードを生成し、自分自身にも多くのトラブルを保存します。
    +0

    私は 'get(key、[、default])'を使うことに慣れていますが、それらの多くを一緒にチェーンする必要がありますが、より具体的にすべきでした。 js ['entry'] ['author'] [0] ['name']。get( '$ t'、None) 'が破損する可能性があります。ありがとう。 –

    2

    質問する内容を処理する方法については、Check hereの辞書の方法を理解する必要があります。

    1

    2つの解決策は、あなたのデータが構成されている方法の詳細を知らなくても、心に来る:

    if k in js['entry']: 
        something = js['entry'][k] 
    

    (このソリューションは、本当にあなたの冗長性の問題を取り除くないだろうが、それはトン以上に簡潔です または

    js['entry'].get(k, []) # or (k, None) depending on what you want to do 
    

    はるかに短いバージョンはちょうど何かのよう...

    for k,v in js['entry']: 
        d[k] = v 
    
    です)/ exceptsでを試してみてください

    もう一度、あなたのデータについてもっと言わなければならないでしょう。

    8

    各try catchブロックを辞書get(key [、default])メソッドの連鎖呼び出しで置き換えます。チェーン内の最後の呼び出しの前に取得するすべての呼び出しには、デフォルトの値{}(空の辞書)が必要です。これにより、後の呼び出しを有効なオブジェクトで呼び出すことができます。あなたがルックアップしようとしているキー。

    は、例えばdictionairies http://docs.python.org/library/stdtypes.html#mapping-types-dict

    のためのPythonドキュメントを参照してください:

    d['links']  = js.get('entry', {}).get('gd$feedLink', []) 
    d['published'] = js.get('entry', {}).get('published',{}).get('$t', '') 
    
    +0

    辞書の 'setdefault'メソッドも参照してください。' defaultdict'に似た、欠落している辞書やリストを実際に追加します。 –

    関連する問題