2012-07-28 16 views
8

Sözlükler içerebilen sözlükler içeren bir sözlüğüm var. ŞuPython - sözlükler içinde iç içe geçmiş değerlere erişme

dictionary = {'ID': 0001, 'Name': 'made up name', 'Transactions': 
       {'Transaction Ref': 'a1', 'Transaction Details': 
        {'Bill To': 'abc', 'Ship To': 'def', 'Product': 'Widget A' 
         ...} ...} ... } 

Ben kimliği 001 için 'Bill To' almak için açma ediyorum, 'İşlem Ref' a1 şöyle: Yardım ancak bu olduğunu düşünüyorum olamaz

if dictionary['ID'] == 001: 
    transactions = dictionary['Transactions'] 
     if transactions['Transaction Ref'] == 'a1': 
      transaction_details = transactions['Transaction Details'] 
      bill_to = transaction_details['Bill To'] 

biraz
bill_to = transactions['Transaction Details']['Bill To'] 

Inter içine açmak zorunda kalmadan aşağı iç içe sözlükleri içine delmek için daha basit bir yaklaşım var mı: - aksak, özellikle son iki satır ben çalışmalıdır aşağıdaki çizgisinde bir şey gibi hissediyorum im değişkenleri?

+6

yapar aslında çalışması gerektiğini hissettiğini hattı. –

cevap

13
bill_to = transactions['Transaction Details']['Bill To'] 

gerçekten çalışıyor. transactions['Transaction Details'], dict numaralı bir ifadedir, böylece arama yapabilirsiniz. Pratik programlar için, iç içe geçmiş dikte bir OO yaklaşımını tercih ederim. collections.namedtuple, yalnızca veri içeren (ve kendi davranışları olmayan) sınıfların birçoğunu hızlı bir şekilde kurmak için özellikle kullanışlıdır.

bir ihtar var: Bazı ortamlarda, sen aramaları yaparken KeyError yakalamak isteyebilirsiniz ve aynı zamanda çalışan bu ortamda, bu sözlükte araması başarısız oldu hangi söylemek zor:

try: 
    bill_to = transactions['Transaction Details']['Bill To'] 
except KeyError: 
    # which of the two lookups failed? 
    # we don't know unless we inspect the exception; 
    # but it's easier to do the lookup and error handling in two steps 
+0

İnanılmaz derecede yararlı - çok teşekkürler! – user1530213

20

kullanabilirsiniz böyle bir şey:

: tek tek parametre olarak arama tuşları tanımlamak istemiyorsanız

>>> def lookup(dic, key, *keys): 
...  if keys: 
...   return lookup(dic.get(key, {}), *keys) 
...  return dic.get(key) 
... 
>>> d = {'a':{'b':{'c':5}}} 
>>> print lookup(d, 'a', 'b', 'c') 
5 
>>> print lookup(d, 'a', 'c') 
None 

Ek olarak, sadece böyle bir liste halinde geçirebilirsiniz

>>> print lookup(d, *['a', 'b', 'c']) 
5 
>>> print lookup(d, *['a', 'c']) 
None 
+0

Umarım sakıncası yoktur, bu işlevin gerçek dinamik arama yeteneğini açıklığa kavuşturmak için bir düzenleme ekledim. Anında arama tuşlarının bir listesini geçme yeteneği, bunu diğer tekniklerin üzerinde bir kesim yapar. –

2

sonra iç içe sözlükleri Burada

>>> dbo={'m':{'d':{'v':{'version':1}}}} 
>>> name='m__d__v__version' # it'll refer to 'dbo['m']['d']['v']['version']', '__' is the separator 
>>> version = reduce(dict.get, name.split('__'), dbo) 
>>> print version 
1 
>>> 

erişmenin bir başka yolu, değişken 'adı' ile 'dbo [' m '] [' d '] [' V '] [' versiyonu '] ', çok daha kısa ve temiz görünüyor.

Bu yöntem, KeyError'u atmayacaktır. Bir anahtar bulunamazsa, 'Yok' alırsınız.

Ref .: http://code.activestate.com/recipes/475156-using-reduce-to-access-deeply-nested-dictionaries/

+0

Eğer ad = 'm__foo__v__foo' yazarsanız bir TypeError atar: TypeError: descriptor 'get' bir 'dict' nesnesi gerektirir, ancak 'NoneType' aldı – krasnaya

İlgili konular