Recursively convert lists to tuples, sets to frozensets, dicts to mappingproxy etc.
Project description
Recursively convert list to tuple, set to frozenset, dict to mappingproxy etc.
Example usage:
import freezedata
data = {'a': [1,2,3], 'b': {1,2,3}, 'c': {1:1, 2:2, 3:3}}
frozendata = freezedata.freeze_data(data)
print(frozendata)
>> {'a': (1, 2, 3), 'b': frozenset({1, 2, 3}), 'c': mappingproxy({1: 1, 2: 2, 3: 3})}
This is a read-only data structure, that is; there is no direct way to alter this data structure from within frozendata itself (without using some special modules (gc, inspect)).
For example:
frozendata[c'][4] = 4
>> TypeError: 'mappingproxy' object does not support item assignment
del frozendata['b']
>> TypeError: 'mappingproxy' object does not support item deletion
Notice: Since a mappingproxy is not hashable, frozen data structures containing mappingproxy (i.e. based on dict) will not be hashable either:
hash(frozendata)
>> TypeError: unhashable type: 'mappingproxy'
On the other hand, if the frozen data structure contains only hashable elements, the whole structure will be hashable (and immutable) as well:
frozendata = freezedata.freeze_data([[1,2,3], {4,5,6}])
print(frozendata)
>> ((1, 2, 3), frozenset({4, 5, 6}))
hash(frozendata)
>> -11948691520864899
Relaxing requirements (accepting functions, classes and instances):
Functions are mutable in Python, but sometimes you still want a function in the new data structure that won’t affect the parent data structure. By setting allow='functions' or allow=['functions'], the new data structure will contain a copy of the included functions:
def func(n):
return n*2
func.a = 'a'
data = [func]
frozendata = freezedata.freeze_data(data, allow='functions')
data[0] == frozendata[0]
>> False
frozendata[0].a = 'b'
print(data[0].a, frozendata[0].a)
>> a b
classes and class instances may be converted into namedtuple and used in the frozen data structure by setting allow={'classes', 'instances} or only one, e.g. allow={'classes'}, as needed. By conveting to namedtuple, informaton may be lost, as parameters with tow leading underscores will be ignored:
class Test:
a = 1
def __init__(self, a):
self.a = a
test = Test(2)
frozendata = freezedata.freeze_data([Test, test], allow={'classes', 'instances'})
print(frozendata)
>> (Test(a=1), Test(a=2))
print(type(frozendata[0]), type(frozendata[1]))
>> <class 'freezedata.freezedata.Test'> <class 'freezedata.freezedata.Test'>
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.