Skip to content

Instantly share code, notes, and snippets.

@homecoder
Last active November 24, 2017 17:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save homecoder/9f37ed975e9a5f4961f0290137d70e70 to your computer and use it in GitHub Desktop.
Save homecoder/9f37ed975e9a5f4961f0290137d70e70 to your computer and use it in GitHub Desktop.
Named Tuple configurable defaults
# Based on code found @ https://stackoverflow.com/a/18348004/7513482
import collections
import sys
def namedtuple_with_defaults(typename, field_names, default_values=(), verbose=False, rename=False, module=None):
"""
Create a namedtuple object with customizable defaults.
Returns a new tuple subclass named typename
:param typename: Name of the tuple subclass created
:param field_names: (str): Space separated list of class attributes
:param default_values: (dict,list,tuple): Setup default values
:param verbose: (bool): Print class definition after build. Outdated, use _source instead.
:param rename: Automatically rename invalid fieldnames (i.e. 'def') to positional arguments rather than fail.
:param module: If module is defined, the __module__ attribute of the named tuple is set to that value.
:return: typename(tuple)
Note: If you wish to see the source, call print(Friend._source) after examples below from python interpreter.
"""
opts = {'verbose': verbose, 'rename': rename, 'module': module}
# Fix for Python < 3.6, < 3.1
py_version = int(''.join(map(str, sys.version_info[:2]))) # Python 2.7 becomes 27, 3.5 = 35, etc.
if py_version < 31:
# Verbose option was added in 3.1
opts = {'verbose': verbose, 'rename': rename}
elif py_version < 36:
# Module was added in 3.6
del opts['module']
T = collections.namedtuple(typename, field_names, **opts)
T.__new__.__defaults__ = (None,) * len(T._fields)
if isinstance(default_values, collections.Mapping):
prototype = T(**default_values)
else:
prototype = T(*default_values)
T.__new__.__defaults__ = tuple(prototype)
return T
# Example:
Friend = namedtuple_with_defaults('Friend','first_name last_name email_address favourite_module least_favourite_module',rename=True,verbose=True)
example1 = Friend(first_name='Guido', last_name='van Rossum', favourite_module='helpista', least_favourite_module=None)
print(example1)
# Output: Friend(first_name='Guido', last_name='van Rossum', email_address=None, favourite_module='helpista', least_favourite_module=None)
# Example 2
example2 = RubyFriend(first_name='Guido', last_name='van Rossum', favourite_module='Rails', least_favourite_module=None)
# Uh oh, an error!
Traceback (most recent call last):
# ... blah blah blah
TypeError: __new__() missing 1 required positional argument: 'email_address'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment