在循环中获取属性名称
我该如何获取一个对象的属性名称和属性值呢?我想把它转换成字典,这样我就可以方便地将这个对象转换成JSON格式。
代码:
class User:
...
def to_dict( self ):
dict = {}
for key, value in filter( lambda aname: not aname.startswith('_'), dir(self) ):
dict[key] = value
return dict
错误:
too many values to unpack
使用:
user = User({
's_email': 'bob@email.com',
's_password': 'password',
})
user.to_dict()
# JSON Serialize
3 个回答
0
我可能漏掉了什么,但为什么不直接用 user.__dict__
呢?
4
你会遇到这个错误是因为 filter( lambda aname: not aname.startswith('_'), dir(u) )
返回的是一个只有单个项的列表,而你却试图同时取出两个值(for key, value
)。使用 dir
而不是 __dict__
的一个可能原因是你想要获取类的属性或者继承的属性。因为 __dict__
只包含实例的属性,所以它找不到这些。
class Base(object):
x = 1
class User(Base):
y = 2
def __init__(self, z):
self.z = z
>>> u = User(3)
>>> u.__dict__
<<< {'z': 3}
如果你还是想用 dir
,可以这样做:
def to_dict(self):
d = {}
for k, v in [(x, getattr(self, x)) for x in dir(self) if not x.startswith('_')]:
if not hasattr(v, '__call__'): d[k] = v # skip methods
return d
>>> u = User(3)
>>> u.to_dict()
<<< {'x': 1, 'y': 2, 'z': 3}
不过,明确地定义属性 就像这个回答中提到的那样,可能是最好的方法。
1
使用 self.__dict__
。它是一个字典,表示这个对象的命名空间。
class User:
...
def to_dict(self):
return dict(
[(k, v) for k, v in self.__dict__.iteritems() if not k.startswith('_')]
)
注意,根据你的代码片段,.to_dict()
返回的字典会包含一个键 'to_dict'
,因为这个函数的名字没有以下划线开头。这可能是你发帖时的一个小错误。
如果你想在返回的字典中包含的属性列表比较小(而且变化不大),我建议你明确列出这些属性。
class User(object):
data_attributes = ('s_email', 's_password')
def to_dict(self):
return dict([(attr, getattr(self, attr) for attr in self.data_attributes])