Skip to content

Instantly share code, notes, and snippets.

@jdowner
Created December 12, 2014 14:19
Show Gist options
  • Save jdowner/2d5ea93a78ecfbab4bbc to your computer and use it in GitHub Desktop.
Save jdowner/2d5ea93a78ecfbab4bbc to your computer and use it in GitHub Desktop.
immutable decorator
import functools
def make_immutable(obj):
"""Tries to create an immutable version of an object
Converts object into a nested structure of named tuples where possible.
Primative types (int, str, float, bool) are unchanged but lists and sets are
converted into tuples. Objects are converted into named tuples.
This is not a terribly sophisticated function and will work best with
objects that contain simple types of data.
Arguments:
obj - the object to convert
Returns:
a namedtuple of the same name as the class of the object pass in
"""
if isinstance(obj, (list, tuple, set)):
return tuple(make_immutable(v) for v in obj)
if type(obj) in (int, str, float, bool):
return obj
try:
name = obj.__class__.__name__
attrs = {}
for key, val in obj.__dict__.items():
value = make_immutable(val)
if value is not None:
attrs[key] = value
return collections.namedtuple(name, attrs.keys())(**attrs)
except (AttributeError, TypeError):
pass
return None
def immutable(f):
"""Decorator that makes return value immutable"""
@functools.wraps(f)
def impl(*args, **kwargs):
return make_immutable(f(*args, **kwargs))
return impl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment