Adi*_*n D 40 python python-dataclasses
我有两个数据类,Route并且Factors. Route包含一个值和三个副本Factors。
Route不知道Factors包含多少个变量。我想获取这些变量的名称,然后获取Factors.
这是我目前拥有的:
@dataclass
class Factors:
do: bool # does it do the route
hub: int # how many of the locations are hubs
def __init__(self, do_init):
self.do = do_init
self.hub = 0 # will add later
def __str__(self):
return "%s" % self.do
@dataclass
class Route:
route: tuple
skyteam: Factors
star: Factors
oneworld: Factors
def __init__(self, route):
self.route = route.get('route')
# this could probably be done with one line loop and a variable with names
self.skyteam = Factors(route.get('skyteam'))
self.star = Factors(route.get('star'))
self.oneworld = Factors(route.get('oneworld'))
def __str__(self):
table = [[self.route, "SkyTeam", "StarAlliance", "OneWorld"]] # var name is fine
for var in Factors.__dict__.get('__annotations__').keys(): # for each factor
factor = [var]
factor.append(self.skyteam.__dict__.get(var))
factor.append(self.star.__dict__.get(var))
factor.append(self.oneworld.__dict__.get(var))
table.append(factor)
return tabulate.tabulate(table, tablefmt='plain')
Run Code Online (Sandbox Code Playgroud)
输入是
{'route': ('BOS', 'DXB'), 'skyteam': True, 'star': True, 'oneworld': True}
Run Code Online (Sandbox Code Playgroud)
电流输出为
@dataclass
class Factors:
do: bool # does it do the route
hub: int # how many of the locations are hubs
def __init__(self, do_init):
self.do = do_init
self.hub = 0 # will add later
def __str__(self):
return "%s" % self.do
@dataclass
class Route:
route: tuple
skyteam: Factors
star: Factors
oneworld: Factors
def __init__(self, route):
self.route = route.get('route')
# this could probably be done with one line loop and a variable with names
self.skyteam = Factors(route.get('skyteam'))
self.star = Factors(route.get('star'))
self.oneworld = Factors(route.get('oneworld'))
def __str__(self):
table = [[self.route, "SkyTeam", "StarAlliance", "OneWorld"]] # var name is fine
for var in Factors.__dict__.get('__annotations__').keys(): # for each factor
factor = [var]
factor.append(self.skyteam.__dict__.get(var))
factor.append(self.star.__dict__.get(var))
factor.append(self.oneworld.__dict__.get(var))
table.append(factor)
return tabulate.tabulate(table, tablefmt='plain')
Run Code Online (Sandbox Code Playgroud)
也许我可以搜索Route包含Factors数据类型的每个变量并迭代这些变量?
And*_*bov 65
您可以使用dataclass.fields
from dataclasses import dataclass, fields
for field in fields(YourDataclass):
print(field.name, getattr(YourDataclass, field.name))
Run Code Online (Sandbox Code Playgroud)
Ian*_*dby 14
可能最简单的方法是 import asdictfrom dataclasses,然后编写如下内容:
for key, value in asdict(route).items():
...
Run Code Online (Sandbox Code Playgroud)
对于小型数据类,将数据类对象复制到新字典的成本比便利性和可读性更重要。
我还会使用它__dataclass_fields__返回变量名称及其类型的字典。例如:
for field in mydataclass.__dataclass_fields__:
value = getattr(mydataclass, field)
print(field, value)
Run Code Online (Sandbox Code Playgroud)
我会保留内置__str__函数,只调用类中的函数visualize或其他内容Route,但这就是品味。__init__除非绝对必要,否则您也不应该重载数据类的 ,只需将输入字典放入默认构造函数即可。
最后一点,尝试使用getattr/setattr过度访问__dict__数据类,它很流行用于__slots__存储其属性,这会以一种不平凡的方式破坏您的代码。
所以我会采用这样的方法,使用tabulate库来处理渲染:
from dataclasses import dataclass, fields
import tabulate
@dataclass
class Factor:
do: bool
hub: int = 0 # this is how to add a default value
@dataclass
class Route:
route: tuple
skyteam: Factor
star: Factor
oneworld: Factor
def __post_init__(self):
# turn Factor parameter dicts into Factor objects
for field in fields(self):
if issubclass(field.type, Factor):
setattr(self, field.name, field.type(getattr(self, field.name)))
def visualize(self):
factors = {
field.name: getattr(self, field.name)
for field in fields(self)
if issubclass(field.type, Factor)
}
rows = [[self.route, *factors]] # header
for field in fields(Factor):
rows.append([field.name, *[getattr(f, field.name) for f in factors.values()]])
print(tabulate.tabulate(rows))
Run Code Online (Sandbox Code Playgroud)
这对于你的例子来说效果很好:
>>> r = Route(**{'route': ('BOS', 'DXB'), 'skyteam': True, 'star': True, 'oneworld': True})
>>> r.visualize()
-------------- ------- ---- --------
('BOS', 'DXB') skyteam star oneworld
do True True True
hub 0 0 0
-------------- ------- ---- --------
Run Code Online (Sandbox Code Playgroud)
如果您向 Factor 类添加更多字段并向 Route 添加更多因子实例,则此解决方案应该继续有效。
| 归档时间: |
|
| 查看次数: |
45033 次 |
| 最近记录: |