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 24 Oct 2018, at 05:13, Philip Martin <philip.martin2...@gmail.com> wrote: > > 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 <http://field.name/>) > serializer = OBJECT_SERIALIZERS.get(field.type, None) > > if serializer: > value = serializer(value) > yield value > > @property > def field_names(self): > return [field.name <http://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 <http://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) > ) > > _______________________________________________ > Python-ideas mailing list > Python-ideas@python.org > https://mail.python.org/mailman/listinfo/python-ideas > Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/