我需要将对象“展平”为对象属性的嵌套dicts。我想要执行此操作的对象通常只是基本类型的容器或以类似方式起作用的其他对象。例如:
class foo(object):
bar = None
baz = None
class spam(object):
eggs = []
x = spam()
y = foo()
y.bar = True
y.baz = u"boz"
x.eggs.append(y)
我需要“扁平化”这个:
{ 'eggs': [ { 'bar': True, 'baz': u'boz' } ] }
stdlib中有什么东西可以帮我吗?如果没有,我是否必须针对所有已知的基类型测试isinstance
以确保我不会尝试转换无法转换的对象(例如:bool)?
修改
这些对象从外部库返回到我的代码,因此我无法控制它们。我可以在我的方法中使用它们,但将它们转换为dicts会更容易(更安全?) - 特别是对于单元测试。
答案 0 :(得分:2)
代码:您可能需要处理其他可迭代类型:
def flatten(obj):
if obj is None:
return None
elif hasattr(obj, '__dict__') and obj.__dict__:
return dict([(k, flatten(v)) for (k, v) in obj.__dict__.items()])
elif isinstance(obj, (dict,)):
return dict([(k, flatten(v)) for (k, v) in obj.items()])
elif isinstance(obj, (list,)):
return [flatten(x) for x in obj]
elif isinstance(obj, (tuple,)):
return tuple([flatten(x) for x in obj])
else:
return obj
<强>错误吗 在您的代码中而不是:
class spam(object):
eggs = []
x = spam()
x.eggs.add(...)
请做:
class spam(object):
eggs = None #// if you need this line at all though
x = spam()
x.eggs = []
x.eggs.add(...)
如果不这样做,则spam
的所有实例都将共享相同的eggs
列表。
答案 1 :(得分:0)
不,标准库中没有任何内容。是的,你必须以某种方式测试类型是基本类型,如str,unicode,bool,int,float,long ......
你可能会创建一个方法的注册表来“序列化”不同的类型,但是这只有在某些类型不应该将所有它的属性序列化时才有用,或者如果你还需要展平类属性等等。
答案 2 :(得分:0)
几乎每个对象都有一个字典(称为__dict__
)及其所有方法和成员
通过某些类型检查,您可以编写一个只筛选出您感兴趣的成员的函数。
这不是一项大任务,但正如chrispy所说,从完全不同的角度审视你的问题是值得的。
答案 3 :(得分:0)
嗯,我对此并不感到自豪,但可以做到以下几点:
以下是一个例子:
class foo(object):
def __init__(self):
self.bar = None
self.baz = None
class spam(object):
delf __init__(self):
self.eggs = []
class Serializable():
def serialize(self):
result = {}
for property in self.__dict__.keys():
result[property] = self.__dict__[property]
return result
foo.__bases__ += (Serializable,)
spam.__bases__ += (Serializable,)
x = spam()
y = foo()
y.bar = True
y.baz = u"boz"
x.eggs.append(y)
y.serialize()
class foo(object):
def __init__(self):
self.bar = None
self.baz = None
class spam(object):
delf __init__(self):
self.eggs = []
class Serializable():
def serialize(self):
result = {}
for property in self.__dict__.keys():
result[property] = self.__dict__[property]
return result
foo.__bases__ += (Serializable,)
spam.__bases__ += (Serializable,)
x = spam()
y = foo()
y.bar = True
y.baz = u"boz"
x.eggs.append(y)
y.serialize()
要指出的事情。如果你没有设置var是init, dict 将无法工作'因为它正在访问实例变量而不是类变量(我想你的意思是实例变量)。其次,确保Serializable不从对象继承,它是否会有
希望它有所帮助!
编辑:如果你只是复制 dict ,请使用deepcopy模块,这只是一个例子:P