Skip to content

Instantly share code, notes, and snippets.

@majgis
Last active December 17, 2015 01:38
Show Gist options
  • Save majgis/5529422 to your computer and use it in GitHub Desktop.
Save majgis/5529422 to your computer and use it in GitHub Desktop.
A defaultnamedtuple which creates a namedtuple with default values when none are given.
""" Additional collections to augment Python's collections module.
"""
from collections import namedtuple
def defaultnamedtuple(
typename,
field_names,
verbose=False,
rename=False,
default_factory=None
):
"""A factory for namedtuples with default values similar to defaultdict.
The default_factory is a callable which returns default values. All
other functionality matches namedtuple. When default_factory is None, the
default, the defaultnamedtuple acts exactly the same as a namedtuple.
"""
tuple_class = namedtuple(typename, field_names, verbose, rename)
class sub_tuple_class(tuple_class):
def __new__(self, *args, **kwargs):
if default_factory:
missing_args = field_names[len(args):]
for missing_arg in missing_args:
if not missing_arg in kwargs:
kwargs[missing_arg] = default_factory()
return super(sub_tuple_class, self).__new__(self, *args, **kwargs)
return sub_tuple_class
if __name__ == '__main__':
import unittest
class defaultnamedtupleTestCase(unittest.TestCase):
""" A test case for defaultnamedtuple class factory"""
def setUp(self):
"""Initial setup for all tests"""
self.class_str = 'Test(x=0, y=0, z=0)'
self.class_name = 'Test'
self.field_names = ['x', 'y', 'z']
self.default_value = 0
self.test_default = defaultnamedtuple(
self.class_name,
self.field_names,
default_factory=lambda:self.default_value
)
self.test_no_default = defaultnamedtuple(
self.class_name,
self.field_names
)
self.reference = namedtuple(self.class_name, self.field_names)
def testNoArgsOrKwargs(self):
"""Test defaultnamedtuple with no args or kwargs"""
a = self.test_default()
b = self.reference(
self.default_value,
self.default_value,
self.default_value
)
self.assertEqual(a, b)
def testSomeArgs(self):
"""Test defaultnamedtuple with some but not all args given."""
a = self.test_default(1, 1)
b = self.reference(
1,
1,
self.default_value
)
self.assertEqual(a, b)
def testSomeKwargs(self):
"""Test defaultnamedtuple with some but not all kwargs given."""
a = self.test_default(x=1, z=1)
b = self.reference(
x=1,
y=self.default_value,
z=1
)
self.assertEqual(a, b)
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment