Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Quick and dirty datatypes (DTO)

Tags:

python

dto

Very often, I find myself coding trivial datatypes like

class Pruefer:     def __init__(self, ident, maxNum=float('inf'), name=""):         self.ident  = ident         self.maxNum = maxNum         self.name   = name 

While this is very useful (Clearly I don't want to replace the above with anonymous 3-tuples), it's also very boilerplate.

Now for example, when I want to use the class in a dict, I have to add more boilerplate like

    def __hash__(self):         return hash(self.ident, self.maxNum, self.name) 

I admit that it might be difficult to recognize a general pattern amongst all my boilerplate classes, but nevertheless I'd like to as this question:

  • Are there any popular idioms in python to derive quick and dirty datatypes with named accessors?

  • Or maybe if there are not, maybe a Python guru might want to show off some metaclass hacking or class factory to make my life easier?

like image 212
Jo So Avatar asked Dec 18 '12 12:12

Jo So


2 Answers

>>> from collections import namedtuple >>> Pruefer = namedtuple("Pruefer", "ident maxNum name") >>> pr = Pruefer(1,2,3) >>> pr.ident 1 >>> pr.maxNum 2 >>> pr.name 3 >>> hash(pr) 2528502973977326415 

To provide default values, you need to do little bit more... Simple solution is to write subclass with redefinition for __new__ method:

>>> class Pruefer(namedtuple("Pruefer", "ident maxNum name")): ...     def __new__(cls, ident, maxNum=float('inf'), name=""): ...         return super(Pruefer, cls).__new__(cls, ident, maxNum, name) ...  >>> Pruefer(1) Pruefer(ident=1, maxNum=inf, name='') 
like image 186
Alexey Kachayev Avatar answered Sep 20 '22 23:09

Alexey Kachayev


One of the most promising things from with Python 3.6 is variable annotations. They allow to define namedtuple as class in next way:

In [1]: from typing import NamedTuple  In [2]: class Pruefer(NamedTuple):    ...:     ident: int    ...:     max_num: int    ...:     name: str    ...:       In [3]: Pruefer(1,4,"name") Out[3]: Pruefer(ident=1, max_num=4, name='name') 

It same as a namedtuple, but is saves annotations and allow to check type with some static type analyzer like mypy.

Update: 15.05.2018

Now, in Python 3.7 dataclasses are present so this would preferable way of defining DTO, also for backwardcompatibility you could use attrs library.

like image 27
skhalymon Avatar answered Sep 19 '22 23:09

skhalymon