[Python-ideas] Python 3.7 dataclasses attribute order
Anders Hovmöller
boxed at killingar.net
Wed Oct 24 05:30:53 EDT 2018
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.martin2007 at 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 at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20181024/de41b909/attachment-0001.html>
More information about the Python-ideas
mailing list