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