目录
__dict__只能存储实例变量,不能存储类变量
情况一:(可以直接通过__dict__序列化对象)
情况二:(不能直接通过__dict__序列化对象)
情况三:(定义keys和__getitem__方法)
关于细节方面的测试
先给结论:python不能直接序列化对象(往下看)
对于普通得python对象来说,__dict__就可以序列化对象。
__dict__的作用:把类的实例对象的实例属性以字典形式返回。简单的说就是 用来存储实例变量
但是如果对象里面的属性又是另外一个对象,那么这样就很容易出现递归好多对象,这样就无法直接序列化了。
情况如下图:
解决办法:
在代码中设置一个默认方法,按照下面写就行
整体测试代码如下:
注意上图return的一定要是个序列,可以是元组也可以是列表。
使用dict的方式如下, 如果直接使用会报错.
a = A()
dict(a)
使用dict之时,将自动调用类中的keys方法,keys中定义了字典的键,调用keys方法后,程序将依照字典取值的方式尝试获得这些键对应的值。
当使用如字典的取值方式时: 比如a['name'],可以看到a['name']这样的方式是用来访问一个字典的,但是很明显我们的a不是一个字典,而是一个对象,如果对象想以a['name']这样的方式访问,我们就需要为对象增加一个方法叫__getitem__,当python遇到 对象[] 的方式的时候就会调用类中的__getitem__方法, 然后把name当做item参数传递进来,__getitem__方法返回的这个值就是a['name']所调用的结果
因此只需要在一例中添加两个方法就可以使对象可以通过dict转字典:
def keys(self):
return ('name', 'age' )
def __getitem__(self, item):
return getattr(self, item)
通过这种方式, 既可以支持类变量的转换, 又可以自定义需要转换的字段.
完整代码:
class A(object):
name = 'jenrey'
age = 18
def __init__(self):
self.gender = 'male'
def keys(self):
'''当对实例化对象使用dict(obj)的时候, 会调用这个方法,这里定义了字典的键, 其对应的值将以obj['name']的形式取,
但是对象是不可以以这种方式取值的, 为了支持这种取值, 可以为类增加一个方法'''
return ('name', 'age', 'gender')
def __getitem__(self, item):
'''内置方法, 当使用obj['name']的形式的时候, 将调用这个方法, 这里返回的结果就是值'''
return getattr(self, item)
a = A()
r = dict(a)
print(r)
class D:
name = 'zhangsan'
age = 18
def __init__(self):
self.sex = '男'
def keys(self):
return ('name', 'age', 'sex')
def __getitem__(self, item):
return "111"
d = D()
print(d.__dict__) # {'sex': '男'}
print(dict(d)) # {'name': '111', 'age': '111', 'sex': '111'}
如何通过对象下面的属性名字来拿到这个属性的值呢?
就需要使用getattr方法(下图)
class D:
name = 'zhangsan'
age = 18
def __init__(self):
self.sex = '男'
def keys(self):
return ('name', 'sex')
def __getitem__(self, item):
return getattr(self, item)
d = D()
print(d.__dict__) # {'sex': '男'}
print(dict(d)) # {'name': 'zhangsan', 'sex': '男'} 如果注销了getitem方法就会报错TypeError: 'D' object is not iterable
keys方法只return一个只有一个元素的元组的时候会报错AttributeError: 'D' object has no attribute 'n'
class D:
name = 'zhangsan'
age = 18
def __init__(self):
self.sex = '男'
def keys(self):
return ('name')
def __getitem__(self, item):
return getattr(self, item)
d = D()
print(d.__dict__) # {'sex': '男'}
print(dict(d)) # keys方法只return一个的时候会报错AttributeError: 'D' object has no attribute 'n'
为什么是n呢?而且报错的时候是在getattr方法的时候报错的,这就说明这个getitem方法的形参item传入的是一个n而不是name,这是因为我们想的是 return('name')只是定义了一个元素的元组,但是一个元素的元组不是这么定义的,而是要在后面加入一个,号!return('name',)
class D:
name = 'zhangsan'
age = 18
def __init__(self):
self.sex = '男'
def keys(self):
return ('name',)
def __getitem__(self, item):
return getattr(self, item)
d = D()
print(d.__dict__) # {'sex': '男'}
print(dict(d)) # 注意定义一个元素的元组的时候要在后面加上逗号 {'name': 'zhangsan'}
class D:
name = 'zhangsan'
age = 18
def __init__(self):
self.sex = '男'
def keys(self):
return ['name'] # 是用列表也是可以的,只要是返回序列类型的就可以
def __getitem__(self, item):
return getattr(self, item)
d = D()
print(d.__dict__) # {'sex': '男'}
print(dict(d)) # {'name': 'zhangsan'}