Package: cynamedtuple
cynamedtupleMemory efficient and fastnamedtupleimplementation usingCython.InstallationTo install last released version:pip install cynamedtupleAscynamedtupleusesCythonunder the hood, right C-compler/tool-chain is needed in order to be able to createcynamedtuples.To install the most current version use:pip install https://github.com/realead/cynamedtuple/zipball/masterThe necessaryCython-module will be installed as well, if not already in the installation.UsageWhen providing the types of fields, the resulting tuple is not only named but also typed, i.e. the underlying fields backed by corresponding c-types thus needing less memory:from cynamedtuple import typed_namedtuple
MyStruct = typed_namedtuple("MyStruct", dict(a="int", b="int", c="int"), defaults=[2,3])
s = MyStruct(5)
print(s.a, s.b, s.c)      # results in 5 2 3
print(s[0], s[1], s[-1])  # results in 5 2 3For Python versions with non-ordereddicts (i.e. prior to Py3.6), version with name-type-pairs iterable can be used:...
typed_namedtuple("MyStruct", [("a","int"), ("b","int"), ("c","int")])
...When the fields cannot be statically typed,untyped_namedtuplecan be used, which uses slightly less memory and is somewhat faster than Python's originalnamedtuple:from cynamedtuple import untyped_namedtuple
MyStruct = untyped_namedtuple("MyStruct", ["a", "b", "c"], defaults=[2,3])
s = MyStruct(5)
print(s.a, s.b, s.c)      # results in 5 2 3
print(s[0], s[1], s[-1])  # results in 5 2 3PerformanceLet's compare the performance of the following implementationP=collections.namedtuple("P",["a", "b"])
T=cynamedtuple.typed_namedtuple("T", [("a", "int"), ("b", "int")])
U=cynamedtuple.untyped_namedtuple("U", ["a", "b"])with the built-in (unnamed)tuple.Memory usageMemory usage depends on the used types, usingintinstead of Python's integer means 3-4 times smaller memory footprint. For1e7elements in a list following memory was used:ClassUsed memory (in MB)typed(T)308untyped(U)927Python's(P)1082tuple1006TimingsCreationFor creation of1e6elements, typed cynamedtuple is almost as fast as usual tuple and about 4 times faster than Python'snamedtuple:ClassTimestyped(T)128 msuntyped(U)171 msPython's(P)504 mstuple118 msAccessing fieldsFor accessing a field, typed and untyped versions are about 30% faster than Python'snamedtuplebut slightly slower than the usualtuple:ClassTimestyped(T)51.5 nsuntyped(U)45.5 nsPython's(P)68.4 nstuple49.9 nsAccessing via indexWarning:cynamedtuples aren't optimized for access via index - it is linear in number of fields, thus should not be used if there are many fields.Producing pyx-codeUnder the hood cynamedtuple uses string code snippets from Cython (akacython.inline), and with that some constrains come into play:Cython doesn't not yet supporting any cimports/includes from string code snippetsit is not possible to define any types viactypedefe.g.ctypedef int myintand use them in acynamedtuple, thus the types ofcynamedtupleare limited to the built-in types.A workaround is to usetyped_namedtuple_cycodeto produce the Cython code and to build a cython module from it. Usecython_header-argument to insert needed definitions, e.g.typed_namedtuple_cycode("A", (("a", "myint"),), cython_header = ["ctypedef int myint"])will yield the following cython-code:ctypedef int myint
cdef class A:
    cdef public myint a
    def __init__(self,a):
        self.a = a
    def __getitem__(self, i):
        if i==0 or i==-1: return self.a
        raise IndexError('tuple index out of range')There is alsountyped_namedtuple_cycode-function as well.Trivia:This project was inspired by the following SO-question:https://stackoverflow.com/q/65159938/5769463.While Python'snamedtuplewas an inspiration,cynamedtupleisn't a simple drop-in replacement.While cnamedtuple (https://pypi.org/project/cnamedtuple/) is all about speed,cynamedtupleis more about smaller memory footprint.History:0.1.0: 13.12.2020:introducing basic functionality