在编写一些服务时,我发现我想从字典中构建Python对象,然后将它们“序列化”回字典中。
当前,我的问题是使用itemgetter
和vars
混合使用的结果。没有给我预期的结果。更具体地说:
from operator import itemgetter
class Object(object):
def __init__(self, foo: str, bar: int):
self.foo, self.bar = foo, bar
@staticmethod
def from_dict(dictionary):
attributes = ["foo", "bar"]
return Object(*itemgetter(*attributes)(dictionary))
因此,我们有一个称为from_dict
的静态方法,该方法应带一个字典并返回一个Object
对象。
这是我想要的行为:
>> d = {"foo": "frobulate", "bar": 42}
>> obj = Object.from_dict(d)
>> vars(obj)
{"foo": "frobulate", "bar": 42}
但是,我得到的却是:
>> d = {"foo": "frobulate", "bar": 42}
>> obj = Object.from_dict(d)
>> vars(obj)
{"foo": ("frobulate",), "bar": (42,)}
其中属性设置为单元素元组。
是否有一种干净的python方式让我得到我期望的行为?
我正在努力避免重复:
class Object(object):
...
@staticmethod
def from_dict(dictionary):
return Object(foo=dictionary["foo"],bar=dictionary["bar"])
最终,我希望有一个通用方法,该方法采用一个类cls
并可以解析字典中的任何对象:
def parse_object_from_dict(cls, attributes, dictionary):
return cls(*itemgetter(*attributes)(dictionary))
可以这样使用:
>> foo = parse_object_from_dict(Foo, ["a", "b"], {"a": 42, "b": 42})
>> obj = parse_object_from_dict(Object, ["foo", "bar"], {"foo": 42, "bar": 42}
并按预期设置属性(而不是单元素元组!)。
这可能吗?甚至是个好主意?
答案 0 :(得分:2)
对于所描述的内容,应该使用类方法。您需要输入字典具有与__init__
函数中的参数相同的键,但是除此之外,您还只是将键值对推入对象。
class Object:
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
@classmethod
def from_dict(cls, d):
ob = cls(**d)
for k,v in d.items():
setattr(ob, str(k), v)
return ob
答案 1 :(得分:1)
一种方法是使用setattr
class Object(object):
def __init__(self, foo=None, bar=None):
self.foo = foo
self.bar = bar
@staticmethod
def from_dict(dic):
obj = Object()
[setattr(obj, attr, dic[attr]) for attr in ["foo", "bar"]]
return obj
另一种方法是使用**
,但可能做事草率,并且如果字典中包含多余的键,则可能引发错误。
class Object(object):
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
@staticmethod
def from_dict(dic):
return Object(**dic)
data = {'foo': 'a', 'bar': 2}
o = Object.from_dict(data)
data = {'foo': 'a', 'bar': 2, 'baz': 3}
o = Object.from_dict(data) # this will throw an error due to the 'baz' key
最后一种可能是最干净的方法是尝试使用棉花糖,它可以为您处理序列化和反序列化。
https://marshmallow.readthedocs.io/en/3.0/api_reference.html