如何在Python 3.5中从JSONs初始化类时减少样板文件?
问题描述:
我有一组python webservices,它们可以通过JSON POSTs获取数据对象。在我的旧服务中,我有很多样板可以对每个对象进行序列化和检查JSON。随着Python 3.5s新的打字和PEP 484我有这种感觉,可以大大减少。这值得么?有没有人有一个很好的解决方案?如何在Python 3.5中从JSONs初始化类时减少样板文件?
其他信息
我的老样板看起来像这样为每个对象:
class Data:
class Nested1:
def __init__(self, nested1_flat1):
self.nested1_flat1 = nested1_flat1
@classmethod
def from_jsond(cls, jsond):
# jsond : dict of strings, lists and dicts as usually receivied from reading JSON
kwargs = {}
for key, val in jsond.items():
# lots of code to deal with special objects , e.g.
if key=='date' : kwargs[key] = cleverly_build_datetime_from_js_format(val)
return cls.__init__(**kwargs)
def __init__(self, flat1, nested1):
self.flat1 = flat1
self.nested1 = nested1
@classmethod
def from_jsond(cls, jsond):
kwargs = {}
for key, val in jsond.items():
# lots of code to deal with nested and special objects, e.g.
if key=='nested1' : kwargs[key] = Nested1.from_jsond(val)
return cls.__init__(**kwargs)
我设法减少它归结为以下
@from_jsond
class Data:
@from_jsond
class Nested1:
@auto_assign
@beartype
def __init__(self, nested1_flat1: str):
pass
@auto_assign
@beartype
def __init__(self, flat1: str, nested1: Nested1)
pass
这里我用的片段为@auto_assign和@beartype和我自己的from_jsond。
import inspect
from typing import Any
_JSON_READABLE = [str, list, dict, Any]
def _from_jsond(cls, json_dict):
'''
Entity specific conversion of string dictionary to entity.
The json_dict is a dict of string, lists and other dicts as typically encoded in a JSON.
'''
kwargs = {}
init_parameters = inspect.signature(cls.__init__).parameters
for key, val in json_dict.items():
if key in init_parameters.keys():
if init_parameters[key].annotation in _JSON_READABLE:
kwargs[key] = val
else:
if hasattr(init_parameters[key].annotation, 'from_jsond'):
kwargs[key] = init_parameters[key].annotation.from_jsond(val)
else:
raise TypeError('No method to unserialize type "' + init_parameters[key].annotation.__name__ + '"')
else:
raise AttributeError('Class "' + cls.__name__ + '" does not accept attribute "' + key + '"')
return cls(**kwargs)
def from_jsond(cls):
''' Wrapper to add _from_jsonlike to cls as classmethod '''
cls.from_jsonlike = classmethod(_from_jsond)
return cls
继承可能最有可能进一步减少它,但我不知道是否值得的麻烦和足够稳定。意见和经验,欢迎:)
答
不,PEP 484和类型提示一般不会帮助你减少样板。
最简单的解释是,蟒蛇运行时间不PEP 484 Python解释器执行类型提示只,以确保语法是正确的认识,没有不确定姓名等
因此,没有办法通过使用类型提示来有意义地改变程序的运行时行为。
只有在您执行解释程序之前单独处理类型提示才能验证您的类型是否正确。没有信息从该分析流向python解释器。
当然,您可以在运行时自己阅读源代码的类型注释,然后按照自己的意愿去做。但是这显然不是你要问的,因为为了用这种方法做任何有用的事情,你必须编写许多相当复杂的代码。