@dataclass
class Car:
brand: str
color: str
如何获得忽略 None 值的字典?就像是:
>>> car = Car(brand="Audi", color=None)
>>> asdict(car, some_option_to_ignore_none_values=True)
> {'brand': 'Audi'}
@dataclass
class Car:
brand: str
color: str
如何获得忽略 None 值的字典?就像是:
>>> car = Car(brand="Audi", color=None)
>>> asdict(car, some_option_to_ignore_none_values=True)
> {'brand': 'Audi'}
所有答案都很好,但对我来说它们太冗长了。这是一个单行:
# dc is dataclass
# d is dict out
d = asdict(dc, dict_factory=lambda x: {k: v for (k, v) in x if v is not None})
展示案例:
from typing import Optional, Tuple
from dataclasses import asdict, dataclass
@dataclass
class Space:
size: Optional[int] = None
dtype: Optional[str] = None
shape: Optional[Tuple[int]] = None
s1 = Space(size=2)
s1_dict = asdict(s1, dict_factory=lambda x: {k: v for (k, v) in x if v is not None})
print(s1_dict)
# {"size": 2}
s2 = Space(dtype='int', shape=(2, 5))
s2_dict = asdict(s2, dict_factory=lambda x: {k: v for (k, v) in x if v is not None})
print(s2_dict)
# {"dtype": "int", "shape": (2, 5)}
另一种选择是编写一个 dict_factory 拒绝添加 None 值并将其传递给asdict
方法。在此处查看代码源https://github.com/python/cpython/blob/master/Lib/dataclasses.py
我需要一些递归的东西,所以我从 Ramtin 指向的数据类源代码中借用并添加了几个条件:
from copy import deepcopy
from dataclasses import fields
def dict_minus_none_values(obj, dict_factory=dict):
"""Based on dataclasses._asdict_inner"""
if hasattr(type(obj), "__dataclass_fields__"):
result = []
for field in fields(obj):
value = dict_minus_none_values(getattr(obj, field.name), dict_factory)
if value is not None:
result.append((field.name, value))
return dict_factory(result)
if isinstance(obj, tuple) and hasattr(obj, "_fields"):
return type(obj)(*[dict_minus_none_values(v, dict_factory) for v in obj])
if isinstance(obj, (list, tuple)):
return type(obj)(dict_minus_none_values(v, dict_factory) for v in obj)
if isinstance(obj, dict):
return type(obj)(
(
dict_minus_none_values(k, dict_factory),
dict_minus_none_values(v, dict_factory),
)
for k, v in obj.items()
if v is not None
)
return deepcopy(obj)
class IgnoreNoneValues(dict):
def __setitem__(self, k, v):
if v is not None:
super().__setitem__(k, v)
asdict(<some dataclass object>, dict_factory=IgnoreNoneValues)
使用简单的类
class human:
def __init__(self, choice = False, **kwargs):
self.details = [kwargs if choice is False else self._filterr(kwargs)][0]
def _filterr(self, param):
filtered = {k:v for k,v in param.items() if v is not None}
return filtered
jason = human(choice = True ,name = "jason", age = None, height = None, gender = None, programmer = True)
print(jason.details)
{'name': 'jason', 'programmer': True}
[Program finished]
干得好:
from dataclasses import dataclass
@dataclass
class Car:
brand: str
color: str
def asdict(o, skip_empty=False):
return {k: v
for k, v in o.__dict__.items()
if not (skip_empty and v is None)}
if __name__ == '__main__':
c = Car(brand='BMW', color=None)
print(asdict(c, skip_empty=False))
print(asdict(c, skip_empty=True))
打印:
{'brand': 'BMW', 'color': None}
{'brand': 'BMW'}