當前位置:成語大全網 - 新華字典 - 訪問字典中的對象時可以使用什麽來實現

訪問字典中的對象時可以使用什麽來實現

在python中訪問字典中的元素都是通過下標,但是通過某些方式,我們可以像訪問成員變量那樣訪問字典:

a = {

'foo': 1,

'bar': 2

}

print a.foo

print a.bar

setattr和__getattr__的使用

看如下的代碼:

# coding: utf-8

class Test(object):

def __init__(self):

self.a = 1

self.b = 2

# 設置屬性都會調用

def __setattr__(self, key, value):

print '__setattr__: %s' % key

self.__dict__[key] = value

# __getattr__ 只有在訪問不存在的成員時才會被調用

def __getattr__(self, key):

print '__getattr__: %s' % key

return self.__dict__[key]

if __name__ == '__main__':

t = Test()

print t.a

print t.b

t.c = 12

print t.c

t.c = 13

t.a = 123

print t.d

setattr是每次設置屬性時都會調用,而__getattr 則只有當訪問不存在的元素時才會調用。

對象的屬性均保存在

dict 這個字典中。默認的

setattr 和

getattr__也是訪問這個字典。

通過壹個Storage類的包裝訪問字典

#!/usr/bin/env python

# coding: utf8

import json

class Storage(dict):

def __init__(self, *args, **kw):

dict.__init__(self, *args, **kw)

def __getattr__(self, key):

return self[key]

def __setattr__(self, key, value):

self[key] = value

def __delattr__(self, key):

del self[key]

if __name__ == '__main__':

l = {'foo': 'bar'}

s = Storage(l)

print s.foo

print s['foo']

我們可以看到,經過Storage類的包裝,此時不僅可以通過下標s['foo'],還可以使用s.foo來調用foo對應的元素。

原理很簡單,我們改變了Storage默認的__getattr 和

setattr 實現,默認實現是訪問內部的

dict__,而該邂逅訪問的是基類dict,所以訪問s.foo時,訪問的是內部的dict['foo'],所以能訪問到元素。

json庫loads中的object_hook參數的使用

看如下的代碼,常規的json序列化和反序列化是這樣做:

import json

from decimal import *

obj = {'name': 'haha', 'age': 23, 'height': 1.75}

json_string = json.dumps(obj)

print json_string

new_obj = json.loads(json_string)

print new_obj

我們從上面看到,dict經過包裝,可以改造成Storage,使用訪問屬性的方式訪問元素。json的loads功能也提供了類似的功能。

# coding: utf-8

import json

obj = {'name': 'haha', 'age': 23, 'height': 1.75}

json_string = json.dumps(obj)

from collections import namedtuple

Student = namedtuple('Student',['name', 'age', 'height'])

def object_hook_handler(dict_obj):

return Student(name=dict_obj['name'],

age=dict_obj['age'],

height=dict_obj['height'])

new_obj = json.loads(json_string, object_hook=object_hook_handler)

print new_obj

打印結果為:

Student(name=u'haha', age=23, height=1.75)

可以看到,通過object_hook這個參數傳入壹個函數,將dict改造成壹個有名元組。

其實,在python中,類也可以看做壹個函數,所以直接傳入類名做參數即可。

from collections import OrderedDict

new_obj = json.loads(json_string, object_hook=OrderedDict)

print new_obj

輸出結果為:

OrderedDict([(u'age', 23), (u'name', u'haha'), (u'height', 1.75)])

隱藏Storage

為了使用方便,最好不讓用戶接觸到Storage,所以可以這樣寫:

#!/usr/bin/env python

# coding: utf8

import json

class Storage(dict):

def __init__(self, *args, **kw):

dict.__init__(self, *args, **kw)

def __getattr__(self, key):

return self[key]

def __setattr__(self, key, value):

self[key] = value

def __delattr__(self, key):

del self[key]

def storage_object_hook(dct):

return Storage(dct)

def json_decode(data, *args, **kw):

return json.loads(data, object_hook=storage_object_hook, *args, **kw)

def json_encode(data, *args, **kw):

return json.dumps(data, *args, **kw)

if __name__ == '__main__':

l = {'foo': 'bar'}

l = json_decode(json_encode(l))

print l

print l.foo