简体   繁体   中英

Customise dataclass asdict keynames

How can I create a dataclass that has a custom dict representation?

Example dict output:

{
    '$1': 'foo',
    '$2': 'bar',
    '$3': 'baz'
}

Obviously I can't have dataclass

@dataclass
class Foo:
    $1: str
    ...

I would need it represented as

@dataclass
class Foo:
    one: str
    ...

for example, but I would like dataclasses.asdict(foo) to return with the "$1" etc. key names.

Also it would be great if

x = {
    '$1': 'foo',
    '$2': 'bar',
    '$3': 'baz'
}
foo = Foo(**x)
assert foo.one == 'foo'
assert foo.two == 'bar'
assert foo.three == 'baz'

worked

You can simply pass your own dict_factory argument, which uses your mapping to construct the dict .

@dataclass
class Foo:
    one: str

def factory(kv_pairs):
    m = {
        'one': '$1',
        # etc
    }
    return {m.get(k): v for k, v in kv_pairs}


f = Foo("foo")
assert dataclasses.asdict(f, dict_factory=factory) == {'$1': 'foo'}

For initializing the class, I would go with a custom class method.

m = {'one': '$1'}
m_inv = {v: k for k, v in m.items()}

@dataclass
class Foo:
    one: str

    @classmethod
    def from_dollar_vars(cls, **kwargs):
        return cls(**{m_inv[k]: v for k, v in kv_pairs})

def factory(kv_pairs):
    return {m[k]: v for k, v in kv_pairs}

x = {'$1': 'foo'}
f = Foo.from_dollar_vars(**x)
assert dataclasses.asdict(f, dict_factory=factory) == x

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM