python 数据类参数是否有别名或名称参数?

Is there a alias or name parameter for python dataclass arguments?

我有一个 class 接受很多参数,在 init 方法中我将它们加载到不同命名的参数中。我知道这可能是一个糟糕的设计或其他什么,但我现在不能改变它。我已经尝试了很多东西,但没有真正做到这一点。是否可以在 dataclasses 内完成?

class MyClass:
    def __init__(self, vp):
        self.viewport = vp

我知道这不是数据的预期行为class,但我想知道是否可以采取一些解决方法。

我想要的是数据中的映射class:

@dataclass
class MyClass:
   viewport:str = "" # this should get the value from vp argument if possible

so when I call:
mc = MyClass(vp="foo")
print(mc) should return (MyClass(viewport="foo"))

您可以使用 InitVar 作为 vp 别名。

from dataclasses import dataclass, InitVar


@dataclass
class MyClass:
    viewport: str = ""  # this should get the value from vp argument if possible
    vp: InitVar[str] = None

    def __post_init__(self, vp):
        if vp:
            self.viewport = vp


mc = MyClass(vp="foo")

如果您需要定义很多别名,您也可以编写自己的使用 Field.metadata 的装饰器,如下所示:

from dataclasses import dataclass, field, fields
from functools import wraps


def _wrap_init(original_init):
    @wraps(original_init)
    def __init__(self, *args, **kwargs):
        aliases = {}
        for field in fields(self):
            alias = field.metadata.get("alias")
            if alias is not None:
                value = kwargs.pop(alias)
                aliases[field.name] = value

        original_init(self, *args, **kwargs)

        for name, value in aliases.items():
            setattr(self, name, value)

    return __init__


def aliased(cls):
    original_init = cls.__init__
    cls.__init__ = _wrap_init(original_init)
    return cls


@aliased
@dataclass
class MyClass:
    viewport: str = field(default="", metadata={"alias": "vp"})


mc = MyClass(vp="foo")

我看不出任何情况下这是个好主意,但您可以这样做:

from dataclasses import dataclass, field, InitVar
@dataclass
class MyClass:
    vp: InitVar[str]
    viewport: str = field(init=False)
    def __post_init__(self,vp):
        self.viewport = vp
        
MyClass(vp='hola')

哪个 return:

MyClass(viewport='hola')

这行得通吗?

from dataclasses import dataclass


arg_dict = {'vp':'viewport'}

@dataclass
class RealMyClass():
    viewport: str = ''
    some_other_field: int = 10
        
        
class MyClass(RealMyClass):
    def __init__(self, **kwargs):
        super().__init__(**{arg_dict[arg]:value for arg, value in kwargs.items()})


print(MyClass(vp='foo'))
MyClass(viewport='foo', some_other_field=10)