3. Blueprint

The namedtuplex package provides extended named tuples with inheritance and function-style defaults for fields. The parameter passing is designed as member variables of the derived classes implemented by the meta class NamedTupleXABCMeta. The application of the default values relies on the implementation of the actual factory - the optional parameter tuplefactory. The default factory is namedtupledefs.namedtuple with support for default values.

_images/structure.png

Figure: Class Diagram of NamedTupleX zoom

For details on the implemented design refer to “The Implementation Basics of Classes” and “The SW-Design of namedtuplex”.

The provided function namedtuplex could be used as a drop-in replacement of the namedtupledefs [namedtupledefs] and standard namedtuple [namedtuple] class factory as well as the namedtuple_with_abc implementation by Jan Kaliszewski [JANKALI] [NAMEDTUPLEABC] - when used with the standard parameters only. The receipt published by Jan Kaliszewski [NAMEDTUPLEABC] served as a base for the namedtuplex.

3.1. Classes

Just a reminder - in Python anything is a class.

3.1.1. Simple Named Tuple Class

Create a simple class:

from __future__ import print_function

from namedtuplex.abc import NamedTupleXABC, ABC

class MyClass(NamedTupleXABC):
    _fields = ('a', 'b', )             # defines the fields of the namedtuple
    pass
assert issubclass(MyClass, ABC)

mynamedtuple = MyClass(11, 22)
assert mynamedtuple[0] == 11
assert mynamedtuple[1] == 22

print("OK")

3.1.2. Symbolic Field Names

Alternative symbolic names for the fields of the tuple.

from __future__ import print_function

from namedtuplex.abc import NamedTupleXABC, ABC

class MyClass(NamedTupleXABC):
    _fields = ('a', 'b', )        # defines the symbolic names
    pass
assert issubclass(MyClass, ABC)

mynamedtuple = MyClass(11, 22)
assert mynamedtuple[0] == 11
assert mynamedtuple[1] == 22

assert mynamedtuple[0] == mynamedtuple.a
assert mynamedtuple[1] == mynamedtuple.b

print("OK")

3.1.3. Inheritance

Inheritance of abstract and non-abstract classes.

from __future__ import print_function

from namedtuplex.abc import NamedTupleXABC, ABC

class MyClass(NamedTupleXABC):
    _fields = ('a', 'b', )
    pass
assert issubclass(MyClass, ABC)

class MyClassDerived(MyClass):
    _fields = MyClass._fields + ('c',)           # the inheritance of fields requires manual coding
    pass
assert issubclass(MyClassDerived, ABC)

mynamedtuple0 = MyClass(11, 22)
mynamedtuple01= MyClassDerived(11, 22, 33)

print("OK")

For the concept see Class Concept of namedtuplex.abc.

3.1.4. Abstract Inheritance

Creates an abstract tuple class in accordance to [PEP3119], see also [abc].

Example with inherited attribute from a custom abstract class.

from __future__ import print_function

from namedtuplex.abc import NamedTupleXABC, ABC


class MyClassABC0(NamedTupleXABC):        # abstract class
    typeid = 4711                         # standard inheritance for typeid

class MyClassABC1(MyClassABC0):           # abstract class
    formatid = 'xyz'                      # standard inheritance for formid

class MyClass(MyClassABC1):               # non-abstract class
    _fields = ('a', 'b')                  # triggered by _fields

    def __str__(self):
        return "%d(%s): %s / %s" % (self.typeid, self.formatid, self[0], self[1])

mynamedtuple0 = MyClass(11, 22)
print(mynamedtuple0)

For the concept see Inheritance of Abstract Classes.

3.1.5. Mixin

The use of the the generated tuple class as mixin.

from __future__ import print_function

from namedtuplex.abc import NamedTupleXABC


class MyClassABC(NamedTupleXABC):                 # abstract class
    typeid = 4711

class MyBaseClass(MyClassABC):                    # non-abstract class
    _fields = ('a', 'b',)

class MyOtherBaseClass(object):                   # non-abstract and non-tupel class
    def print(self):
        print(str(self._fields))
        print(str(self))

class MyClassL(MyBaseClass, MyOtherBaseClass):
    pass

class MyClassR(MyOtherBaseClass, MyBaseClass):
    pass


mynamedtuple0 = MyClassL(11, 22,)
mynamedtuple0.print()

mynamedtuple1 = MyClassR(11, 22,)
mynamedtuple1.print()

3.1.6. Default Values

Default values for for the fields, supports partial fields for the initialization of the generated class - similar to function arguments [PYFUNC].

from __future__ import print_function

from namedtuplex.abc import NamedTupleXABC, ABC

class MyClass(NamedTupleXABC):
    _fields = ('a', 'b', 'c', )      # defines the fields and the symbolic names

mynamedtuple0 = MyClass(11, 22,      fielddefaults=(('c', 33),)           )  # add dynamic defaults via metaclass
mynamedtuple1 = MyClass(11,          fielddefaults=((  2, 33), ('b', 22),))  # add dynamic defaults via metaclass
mynamedtuple2 = MyClass(11, 55, 66,  fielddefaults=(('c', 33), (  1, 22),))  # add dynamic defaults via metaclass

assert mynamedtuple0[0] == 11
assert mynamedtuple0[1] == 22
assert mynamedtuple0[2] == 33

assert mynamedtuple1[0] == 11
assert mynamedtuple1[1] == 22
assert mynamedtuple1[2] == 33

assert mynamedtuple2[0] == 11
assert mynamedtuple2[1] == 55
assert mynamedtuple2[2] == 66

print("OK")

Or the alternate static variant, which allows only one set of default values for each class:

from __future__ import print_function

from namedtuplex.abc import NamedTupleXABC, ABC

class MyClass(NamedTupleXABC):
    _fields = ('a', 'b', 'c', )        # defines the symbolic names
    _item_defauls = (('c', 33), (1, 22),))

mynamedtuple2 = MyClass(11, 55)

assert mynamedtuple0[0] == 11
assert mynamedtuple0[1] == 55
assert mynamedtuple0[2] == 33

print("OK")