[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