nin*_*ino 2 python attributes class python-dataclasses
我们有这个类:
from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Dict
@dataclass
class BoardStaff:
date: str = datetime.now()
fullname: str
address: str
## attributes to be excluded in __str__:
degree: str
rank: int = 10
badges: bool = False
cases_dict: Dict[str, str] = field(default_factory=dict)
cases_list: List[str] = field(default_factory=list)
Emp = BoardStaff('Jack London', address='Unknown', degree='MA')
Run Code Online (Sandbox Code Playgroud)
作为BoardStaff数据类,可以轻松print(Emp)地接收:
BoardStaff(fullname='Jack London', address='Unknown', degree='MA', rank=10, badges=False, cases={}, date=datetime.datetime(2021, 8, 10, 11, 36, 50, 693428)).
但是,我希望从表示中排除一些属性(即最后 5 个),因此我必须定义__str__方法并手动排除一些属性,如下所示:
def __str__(self):
str_info = {
k: v
for k, v in self.__dict__.items()
if k not in ['degree', 'rank', 'other'] and v
}
return str(str_info)
Run Code Online (Sandbox Code Playgroud)
但是有没有更好的排除方法,比如在定义属性时使用一些参数?
明显的解决方案
只需像fields参数一样定义您的属性repr=False:
from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Dict
@dataclass
class BoardStaff:
date: str = datetime.now()
fullname: str
address: str
## attributes to be excluded in __str__:
degree: str = field(repr=False)
rank: int = field(default=10, repr=False)
badges: bool = field(default=False, repr=False)
cases_dict: Dict[str, str] = field(default_factory=dict, repr=False)
cases_list: List[str] = field(default_factory=list, repr=False)
Emp = BoardStaff('Jack London', address='Unknown', degree='MA')
Run Code Online (Sandbox Code Playgroud)
正如其他人在评论中所建议的那样,通过为属性命名以前导下划线开头,这可以很好地与将属性标记为“私有”一起使用。
更先进的解决方案
如果您正在寻找不涉及用 定义这么多fields的更通用的解决方案repr=False,您可以执行以下操作。它与您自己想到的解决方案非常相似,但它创建了一个__repr__更类似于通常的解决方案dataclass __repr__:
from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Dict
@dataclass
class BoardStaff:
fullname: str
address: str
degree: str
date: str = datetime.now()
rank: int = 10
badges: bool = False
cases_dict: Dict[str, str] = field(default_factory=dict)
cases_list: List[str] = field(default_factory=list)
def __repr__(self):
dict_repr = ', '.join(
f'{k}={v!r}'
for k, v in filter(
lambda item: item[0] in {'fullname', 'address', 'date'},
self.__dict__.items()
)
)
return f'{self.__class__.__name__}({dict_repr})'
Emp = BoardStaff('Jack London', address='Unknown', degree='MA')
print(Emp)
Run Code Online (Sandbox Code Playgroud)
(注意,我不得不稍微重新排序您的字段,因为在没有默认值的参数之前使用默认参数参数会引发错误。)
如果您不想将您的__repr__字段硬编码到您的__repr__方法中,您可以将您的非__repr__字段标记为私有属性,正如@DarkKnight 在评论中所建议的那样,并将其用作您的__repr__方法的信号:
from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Dict
@dataclass
class BoardStaff:
fullname: str
address: str
_degree: str
date: str = datetime.now()
_rank: int = 10
_badges: bool = False
_cases_dict: Dict[str, str] = field(default_factory=dict)
_cases_list: List[str] = field(default_factory=list)
def __repr__(self):
dict_repr = ', '.join(
f'{k}={v!r}'
for k, v in filter(
lambda item: not item[0].startswith('_'),
self.__dict__.items()
)
)
return f'{self.__class__.__name__}({dict_repr})'
Emp = BoardStaff('Jack London', address='Unknown', _degree='MA')
print(Emp)
Run Code Online (Sandbox Code Playgroud)
您甚至可以编写自己的装饰器,__repr__以便在逐个类的基础上为您生成自定义方法。例如,此装饰器将生成__repr__仅包含您传递给装饰器的参数的方法:
from dataclasses import dataclass, field
from datetime import datetime
from typing import List, Dict
from functools import partial
def dataclass_with_repr_fields(
keys, init=True, eq=True, order=False,
unsafe_hash=False, frozen=False, cls=None
):
if cls is None:
return partial(
dataclass_with_repr_fields, keys, init=init,
eq=eq, order=order, unsafe_hash=unsafe_hash,
frozen=frozen)
cls = dataclass(
cls, init=init, repr=False, eq=eq, order=order,
unsafe_hash=unsafe_hash, frozen=frozen
)
def __repr__(self):
dict_repr = ', '.join(
f'{k}={v!r}'
for k, v in filter(
lambda item: item[0] in keys,
self.__dict__.items()
)
)
return f'{self.__class__.__name__}({dict_repr})'
cls.__repr__ = __repr__
return cls
@dataclass_with_repr_fields({'fullname', 'address', 'date'})
class BoardStaff:
fullname: str
address: str
degree: str
date: str = datetime.now()
rank: int = 10
badges: bool = False
cases_dict: Dict[str, str] = field(default_factory=dict)
cases_list: List[str] = field(default_factory=list)
@dataclass_with_repr_fields({'name', 'surname'})
class Manager:
name: str
surname: str
salary: int
private_medical_details: str
Emp = BoardStaff('Jack London', address='Unknown', degree='MA')
print(Emp)
manager = Manager('John', 'Smith', 600000, 'badly asthmatic')
print(manager)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
69 次 |
| 最近记录: |