[Python-ideas] Python 3.7 dataclasses attribute order
Philip Martin
philip.martin2007 at gmail.com
Tue Oct 23 23:13:08 EDT 2018
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)
)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20181023/8f3e737e/attachment.html>
More information about the Python-ideas
mailing list