如何在python中安全地解包dict?
我有一个包装器类——它是一个从后端返回到前端的抽象如何在python中安全地解包dict?,python,python-3.x,Python,Python 3.x,我有一个包装器类——它是一个从后端返回到前端的抽象 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':
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)
例如,当我从elastic获取数据时,我会将其转换为新闻项目
:
return [NewsItem.from_payload(hit['_source'])
for hit in result['hits']['hits']]
@classmethod
def from_payload(cls, payload) -> 'NewsItem':
return cls(*(payload[field] for field in cls._fields))
问题是我不想失败,因为未知的领域可能来自弹性。如何忽略它们(或将其放入单独的专用属性列表
NewsItem.extra
)?由于您的问题在于未知键,因此可以使用字典的get方法安全地忽略未知键
对于get方法,第一个参数是您要查找的键,第二个参数是在找不到键时返回的默认值
因此,请执行以下操作
return [NewsItem.from_payload(hit['_source'])
for hit in result.get('hits',{}).get('hits',"NOT FOUND"):
以上只是一个例子。当点击没有你想要的键时,一定要修改你想要的内容。我认为最优雅的方法是使用
新闻项目的字段:
return [NewsItem.from_payload(hit['_source'])
for hit in result['hits']['hits']]
@classmethod
def from_payload(cls, payload) -> 'NewsItem':
return cls(*(payload[field] for field in cls._fields))
如果您想保留extras,您需要做一些工作(字段extra
声明为extra:dict={}
):
您可以进一步优化这一点,使用集合进行过多计算;)
当然,我的解决方案不能处理有效负载
不包含新闻项
的所有字段的情况。您可以使用**kwargs
让您的\uu init\uuu
接受任意数量的关键字参数(“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
类属性的替代解决方案(请参见@morozinic answer+comment)您是否担心结果字典中的键?是的,hit[''u source]
可以包含一些在新闻项中不存在的额外字段。我想忽略它们,并且在from\u payload
什么是NamedTuple
?如果点击['''u source']
包含一些其他键,而不是(id、标题、内容、服务、发布位置
)怎么办?我想你的算法会失败的。嘿,我刚才告诉你如何在使用字典的时候使用自动防故障方法。所以,当你试图访问一个密钥时,使用get方法。我确实提到过,这只是回答中的一个例子。如果你想访问hit,只需执行,hit。get(“_source”,“NA”)你无法理解OP,也无法理解注释!“当然,我的解决方案不能处理有效载荷
不包含新闻项
的所有字段的情况。”是的,它包含,但有一点小小的更改:**{field:payload.get(field)for field in cls.\u fields}
谢谢,但是我从输入import NamedTuple
@petrush中得到了属性错误:无法覆盖NamedTuple属性\uuuu初始化\uuuuu
,请参见修复