我有一个包装类 - 它是一个抽象,我从后端返回到前端。
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
)?
答案 0 :(得分:2)
我认为最优雅的方法是使用._fields
的{{1}}:
NewsItem
如果你想保留额外内容,你需要做一些工作(字段@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
答案 1 :(得分:1)
您可以使用**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回答+评论)
答案 2 :(得分:0)
由于你的问题是使用未知密钥,你可以使用字典的get方法来安全地忽略未知密钥。
对于get方法,第一个参数是您要查找的键,第二个参数是默认值,当找不到键时将返回该值。
所以,请执行以下操作
return [NewsItem.from_payload(hit['_source'])
for hit in result.get('hits',{}).get('hits',"NOT FOUND"):
以上只是一个例子。当命中没有你想要的密钥时,修改你想要的东西。