I made a crazy thing called typed tuple

What is typedtuple?

To put it plainly, it can be described declaratively in the format of voluptuous / named tuple that validates at the time of generation. It is intended for so-called case class use.

A little more detail

For example, when handling various row items in a DB, you can use a raw dict, but I want to type it so that the intention can be conveyed by subscript access or the dull code itself, but it is too match to define the class for that. Don't you think? I have

Also, you can use toolz or fn.py to write in python like FP, Don't you think you want an immutable object? I have

Both of these are problems that can be solved simply by using namedtuple, but on top of that, it is necessary to check what the attribute type is now, which becomes troublesome when writing a large amount of application code. There was, for example, that I wanted to automatically convert ISO-8601 strings to datetime.

In response to this situation, typedtuple aims to provide an implementation in which type checking and conversion are automatically performed when a namedtuple is created simply by declaratively describing the type structure.

How to use

I wrote a lot in here, but use typedtuple.TypedTuple in the same way as namedtuple or use typedtuple.schema decorator (property and method for TypedTuple) If you want to add), define the type by specifying voluptuous.Schema. When creating an instance, value verification and automatic conversion are performed using the specified Schema. For verification / conversion by voluptuous, refer to the document and code there.

from typedtuple import TypedTuple
from voluptuous import Coerce

Vector = TypedTuple('Vector', {'x': Coerce(float), 'y': Coerce(float)})

v0 = Vector(x=10, y='20.0')

# voluptuous.Coerce will automatically convert anything that can be converted to float
print v0  # Vector(x=10.0, y=20.0)

v1 = Vector(x='x', y=20.0)  # raises exception

# TypedTuple=Since it is namedtuple and immutable, updating the attribute is namedtuple._Will use replace to generate another value
v2 = v0._replace(y=30.0)  

important point

Since the structure is specified by dict, which does not guarantee the order of elements, it is not possible to specify the order of attributes as it is even though it is actually tuple. It shouldn't be a problem for basic usage, but if you want to specify the order strictly, you can use collections.OrderedDict.

from collections import OrderedDict
from typedtuple import TypedTuple
from voluptuous import Coerce

Vector = TypedTuple('Vector', OrderedDict((('x', Coerce(float)), ('y', Coerce(float))))
print Vector._fields  #you have to('x', 'y', 'z')become(OrderedDictを使わない場合、順序は不定become)

Another caveat is that it's probably quite heavy to generate. Maybe it can't be helped, so take a benchmark.

Other examples

from voluptuous import All, Range, Length, Optional
from typedtuple import schema

@schema({
    'id': All(int, Range(min=0)),                #id is always a positive integer
    'password': All(str, Length(min=8)),  #password is a string of 8 or more characters
    'first_name': str,
    'last_name': str,
    Optional('nickname'): str,            #Can be omitted when generating if set to Optional
})
class User(object):
    # typedtuple(Or rather named tuple)Cannot add attributes, but can add properties and methods
    @property
    def full_name(self):
        return '{} {}'.format(self.first_name, self.nick_name)

# raises exception
alice = User(id=-1, password='xxxxxxxx', first_name='Alice', last_name='Kakehashi', nick_name='kkhs')

# raises exception
bob = User(id=1, password='short', first_name='Bob', last_name='Kakehashi', nick_name='kkhs')

# nick_name is optional
carol = User(id=2, password='xxxxxxxx', first_name='Carol', last_name='Kakehashi')

the end

I will write about voluptuous soon.

Recommended Posts

I made a crazy thing called typed tuple
I made a python text
I made a discord bot
I made a C ++ learning site
I made a Line-bot using Python!
I made a CUI-based translation script (2)
I made a wikipedia gacha bot
I made a fortune with Python.
I made a CUI-based translation script
I made a daemon with Python
I made a game called Battle Ship using pygame and tkinter
I put in a Bash called Powerline-shell that makes me crazy
I made a dash docset for Holoviews
I made a payroll program in Python!
I touched "Orator" so I made a note
I made a character counter with Python
Beginner: I made a launcher using dictionary
I made a conversation partner like Siri
I made a script to display emoji
I made a Hex map with Python
I made a life game with Numpy
I made a stamp generator with GAN
I made a browser automatic stamping tool.
After studying Python3, I made a Slackbot
I made a roguelike game with Python
I made a simple blackjack with Python
I made a configuration file with Python
I made a library for actuarial science
I made a WEB application with Django
I made a neuron simulator with Python
I made a stamp substitute bot with line
I made a python dictionary file for Neocomplete
I made a competitive programming glossary with Python
I made a weather forecast bot-like with Python.
I made a spare2 cheaper algorithm for uWSGI
I made a useful tool for Digital Ocean
I made a GUI application with Python + PyQt5
I made a Twitter fujoshi blocker with Python ①
[Python] I made a Youtube Downloader with Tkinter.
I made a router config collection tool Config Collecor
I made a simple Bitcoin wallet with pycoin
I made a downloader for word distributed expression
I made a LINE Bot with Serverless Framework!
I made a tool to compile Hy natively
I made a tool to get new articles
I made a random number graph with Numpy
I made a peeping prevention product for telework.
I made a simple RSS reader ~ C edition ~
I made a Caesar cryptographic program in Python.
I made a bin picking game with Python
I made a Mattermost bot with Python (+ Flask)
I made a Python Qiita API wrapper "qiipy"
I made a QR code image with CuteR
[AWS] I made a reminder BOT with LINE WORKS
I made a Twitter BOT with GAE (python) (with a reference)
I made a prime number generation program in Python
I actually statically typed a suitable snippet with mypy
I made a user management tool for Let's Chat
I made a login / logout process using Python Bottle.
I made a ready-to-use syslog server with Play with Docker
I made a Christmas tree lighting game with Python