python 什么是一个更好的方法来转换类键和值?

ncecgwcz  于 2023-11-15  发布在  Python
关注(0)|答案(6)|浏览(129)

我有两个类RouteFactorsRoute包含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')

字符串
输入

{'route': ('BOS', 'DXB'), 'skyteam': True, 'star': True, 'oneworld': True}


电流输出

('BOS', 'DXB')  SkyTeam  StarAlliance  OneWorld
do              True     True          True
hub             0        0             0


也许我可以在Route中搜索每个包含Factors数据类型的变量,然后在这些变量上搜索?

uyhoqukh

uyhoqukh1#

你可以用玻璃。

from dataclasses import dataclass, fields

for field in fields(YourDataclass):
    print(field.name, getattr(YourDataclass, field.name))

字符串

kgsdhlau

kgsdhlau2#

我还使用了__dataclass_fields__,它返回变量名及其类型的dict。例如:

for field in mydataclass.__dataclass_fields__:
    value = getattr(mydataclass, field)
    print(field, value)

字符串

xxslljrj

xxslljrj3#

可能最简单的方法是从dataclasses导入asdict,然后写这样的代码:

for key, value in asdict(route).items():
    ...

字符串
对于一个小的类,将类对象复制到一个新字典的成本远远超过了它的方便性和可读性。

3htmauhk

3htmauhk4#

我不去管内置的__str__ s,只在Route类上调用函数visualize或其他东西,但这是有品味的。你也不应该重载__init__类,除非你绝对需要,只要把你的输入dict放在默认的构造函数中。
最后一点,尝试使用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))

字符串
这对你的例子来说很好:

>>> 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
--------------  -------  ----  --------


如果您向Factor类添加更多字段,并向Route添加更多因子示例,此解决方案应继续有效。

vkc1a9a2

vkc1a9a25#

为了访问类本身中的字段,我尝试了以下操作。

from dataclass import dataclass, fields

@dataclass
class someDataclass:
    def access_fields(self):
        for field in fields(self.__class__):
            print(field) # you get the Field() instances

字符串

aoyhnmkz

aoyhnmkz6#

要遍历键值对,可以将此方法添加到类中:

def items(self):
    for field in dataclasses.fields(self):
        yield field.name, getattr(self, field.name)

字符串
然后像往常一样循环:

for key, value in obj.items():
    do_stuff(key, value)

相关问题