2013-02-08 2 views
1

Я смущен, почему я должен использовать `.get («ключ») при попытке получить доступ к массиву объектов из файла JSonпитон JSON словарь прямой доступ

req = urllib2.Request("http://website.com/entertainment/entertainment_news.json", None) 
opener = urllib2.build_opener() 
f = opener.open(req) 
stories = json.load(f) 
for new_story in stories: 
    #Why can't I access variables using 
    new_story.title 

    #I have to do 
    new_story.get('title') 

ответ

7

Ваша проблема в том, что, когда в json модуль анализирует объект JSON, он возвращает Python dict, что является более подходящей структурой данных в Python для данных.

Это означает, что вы не хотите пытаться получить доступ к полю на нем, а скорее получить доступ к элементу в dict. Синтаксис Python для доступа к элементу из dict с (или dict -как объектов) является:

dict[name] 

Так что в вашем случае:

new_story['title'] 

См the documentation for dicts для получения дополнительной информации.

dict.get() функция позволяет легко получить значение по умолчанию (по умолчанию None), если ключ не существует (как правило, это произведет KeyError. Вы обычно не хотите, чтобы это поведение (это, как правило, лучше чтобы избежать ошибки раньше, и узнать, где проблема, чем получить значение None и получить ошибки позже, когда вы попытаетесь ее использовать).

Также обратите внимание, что это хороший прецедент для оператора with, чтобы убедиться, что соединение закрывается должным образом. Поскольку urllib2 не поддерживает контекстных менеджеров по умолчанию, мы используем contextlib.closing(), чтобы сделать один:

from contextlib import closing 
req = urllib2.Request("http://website.com/entertainment/entertainment_news.json", None) 
opener = urllib2.build_opener() 
with closing(opener.open(req)) as f: 
    stories = json.load(f) 
    ... 
0

Потому что вы должны использовать new_story [ «названия»], но если этот ключ не будет существовать, он будет бросать вас исключением

0

В дополнении к ответу Lattyware в: для того, чтобы иметь возможность получить доступ к Dict используя .some_attribute конвенции, вы можете использовать трюк:

class Story: 
    def __init__(self, **kwargs): 
    self.__dict__.update(kwargs) 

#...  
stories = [Story(story) for story in json.load(f)] 
for new_story in stories: 
    # now you can do it! 
    new_story.title 

... хотя это сделать, если вы действительно хотите придерживаться «точка» нотации. Это просто приносит еще одно осложнение вашей программе (кроме многих других недостатков, например, story.title.somethingelse не будет работать в этом простом сценарии без какой-либо рекурсивной инициализации)

Вы также можете рассмотреть возможность использования namedtuple.

+0

Если бы я должен был сделать это взломать (чего я бы не хотел, но я отвлекся), я бы, вероятно, сделал это, выполнив метод '__getattr __()', который просто сделал return self [key] '. –

+0

Вы также можете выполнить 'params = type (" Параметры ", (object,), dict_with_parameters)' –

Смежные вопросы