Python 3.7 dataclasses attribute order

Hi, I just started to use the new dataclasses module. My initial use case boils down to somewhere between a namedtuple and a class where I want a record with a few methods. Mainly, I am trying to build a specific record from various sources, and then have the class handle validation and serialization. One roadblock I have found is that I can't use the field order I define for the class to say write out a csv file if any of the fields have default value. I know this bucks Python's args, kwargs ordering, but I think having the ability define optional arguments and required arguments in any order helps improve the classes intended usability. For instance, imagine "account_description_2" is None for most sources, but must appear before "other_required_field" in a CSV exported file. I think it would be useful to be able to do the following: import csv from datetime import date from dataclasses import dataclass, fields from typing import List OBJECT_SERIALIZERS = {date: date.isoformat} @dataclass class Account: account_id: str account_description: str account_description_2: str = None # INVALID other_required_field: str def serialize(self): for field in fields(self): value = getattr(self, field.name) serializer = OBJECT_SERIALIZERS.get(field.type, None) if serializer: value = serializer(value) yield value @property def field_names(self): return [field.name for field in fields(self)] @classmethod def from_source_a(cls, record): return cls(account_id=record['account_code'], account_description=record['account_name'], other_required_field=record['other_field']) @dataclass class AccountList: accounts: List[Account] @property def field_names(self): return [ field.name for field in fields(fields(self)[0].type.__args__[0]) ] @property def record_field(self): return fields(self)[0].name def to_csv(self, path): with open(path, 'w') as file: self.write_file(file) def write_file(self, file): records_field = self.record_field writer = csv.writer(file) writer.writerow(self.field_names) writer.writerows( record.serialize() for record in getattr(self, records_field) )

Well that seems super unfortunate. You can opt out of the auto generate constructor and do it yourself: @dataclass(init=False) class Foo: foo: str bar: str = None baz: str def __init__(self, *, foo, bar = None, baz): self.foo = foo self.bar = bar self.baz = baz Foo(foo='a', bar='b', baz='c') but this seems to take away from the utility of dataclasses. One could imagine there being a new argument to @dataclass that would make this work. Something like: @dataclass(init_kwargs_only=True) class Foo: foo: str bar: str = None baz: str where you would then get an auto generated constructor like with keyword only arguments. Personally I think this should have been the default, but it's at least a nice addition now. / Anders

On 10/24/2018 5:30 AM, Anders Hovmöller wrote:
https://bugs.python.org/issue33129 I definitely wouldn't want this to be the default. And as you say, it's too late anyway. I haven't decided how the interaction of per-field and whole class versions of keyword-only should operate. Eric

Well that seems super unfortunate. You can opt out of the auto generate constructor and do it yourself: @dataclass(init=False) class Foo: foo: str bar: str = None baz: str def __init__(self, *, foo, bar = None, baz): self.foo = foo self.bar = bar self.baz = baz Foo(foo='a', bar='b', baz='c') but this seems to take away from the utility of dataclasses. One could imagine there being a new argument to @dataclass that would make this work. Something like: @dataclass(init_kwargs_only=True) class Foo: foo: str bar: str = None baz: str where you would then get an auto generated constructor like with keyword only arguments. Personally I think this should have been the default, but it's at least a nice addition now. / Anders

On 10/24/2018 5:30 AM, Anders Hovmöller wrote:
https://bugs.python.org/issue33129 I definitely wouldn't want this to be the default. And as you say, it's too late anyway. I haven't decided how the interaction of per-field and whole class versions of keyword-only should operate. Eric
participants (3)
-
Anders Hovmöller
-
Eric V. Smith
-
Philip Martin