如何在 python 中安全地解压缩字典?



我有一个包装类 - 这是一个从后端返回到前端的抽象。

from typing import NamedTuple
class NewsItem(NamedTuple):
id: str
title: str
content: str
service: str
published_at: datetime
@classmethod
def from_payload(cls, payload) -> 'NewsItem':
return cls(**payload)

例如,当我从弹性获取数据时,我将其转换为NewsItem

return [NewsItem.from_payload(hit['_source'])
for hit in result['hits']['hits']]

问题是我不想因为来自弹性的未知字段而失败。如何忽略它们(或放入单独的专用属性列表NewsItem.extra(?

我认为最优雅的方法是使用NewsItem._fields

@classmethod
def from_payload(cls, payload) -> 'NewsItem':
return cls(*(payload[field] for field in cls._fields))

如果你想保留额外的内容,你需要做一些工作(字段extra声明为extra: dict = {}(:

@classmethod
def from_payload(cls, payload) -> 'NewsItem':
fields_no_extra = set(cls._fields) - {'extra'}
extra_fields = payload.keys() - fields_no_extra
extras = {field: payload[field] for field in extra_fields}
data = {field: payload[field] for field in fields_no_extra}
data['extra'] = extras
return cls(**data)

你可以进一步优化这一点,用集合进行过多的计算;(

当然,我的解决方案无法处理payload不包含NewsItem的所有字段的情况

您可以使用**kwargs让您的__init__采用任意数量的关键字参数("kwargs"表示"关键字参数"(并丢弃不必要的参数:

class NewsItem(NamedTuple):
id: str
title: str
content: str
service: str
published_at: datetime
@classmethod
def from_payload(cls, id=None, title=None, content=None, service=None, published_at=None, **kwargs) -> 'NewsItem':
return cls(id, title, content, service, published_at)

具有内省NamedTuple类属性的替代解决方案(请参阅@MOROZILnic答案+注释(

由于您的问题出在未知键上,因此您可以使用字典的 get 方法来安全地忽略未知键。

对于 get 方法,第一个参数是您正在寻找的键,第二个参数是默认值,当找不到键时将返回该值。

因此,请执行以下操作

return [NewsItem.from_payload(hit['_source'])
for hit in result.get('hits',{}).get('hits',"NOT FOUND"):

以上只是一个例子。 当命中没有您想要的键时,请修改您想要获得的内容。

最新更新