Assignment & Mutation¶
By default, glom aims to safely return a transformed copy of your data. But sometimes you really need to transform an existing object.
When you already have a large or complex bit of nested data that you
are sure you want to modify in-place, glom has you covered, with the
assign()
function, and the Assign()
specifier
type.
Contents
Assignment¶
Deeply assign within an existing structure, given a path and a value.
- glom.assign(obj, path, val, missing=None)[source]¶
New in glom 18.3.0
The
assign()
function provides convenient “deep set” functionality, modifying nested data structures in-place:>>> target = {'a': [{'b': 'c'}, {'d': None}]} >>> _ = assign(target, 'a.1.d', 'e') # let's give 'd' a value of 'e' >>> pprint(target) {'a': [{'b': 'c'}, {'d': 'e'}]}
Missing structures can also be automatically created with the missing parameter. For more information and examples, see the
Assign
specifier type, which this function wraps.
- class glom.Assign(path, val, missing=None)[source]¶
New in glom 18.3.0
The
Assign
specifier type enables glom to modify the target, performing a “deep-set” to mirror glom’s original deep-get use case.Assign
can be used to perform spot modifications of large data structures when making a copy is not desired:# deep assignment into a nested dictionary >>> target = {'a': {}} >>> spec = Assign('a.b', 'value') >>> _ = glom(target, spec) >>> pprint(target) {'a': {'b': 'value'}}
The value to be assigned can also be a
Spec
, which is useful for copying values around within the data structure:# copying one nested value to another >>> _ = glom(target, Assign('a.c', Spec('a.b'))) >>> pprint(target) {'a': {'b': 'value', 'c': 'value'}}
Another handy use of Assign is to deep-apply a function:
# sort a deep nested list >>> target={'a':{'b':[3,1,2]}} >>> _ = glom(target, Assign('a.b', Spec(('a.b',sorted)))) >>> pprint(target) {'a': {'b': [1, 2, 3]}}
Like many other specifier types,
Assign
’s destination path can be aT
expression, for maximum control:# changing the error message of an exception in an error list >>> err = ValueError('initial message') >>> target = {'errors': [err]} >>> _ = glom(target, Assign(T['errors'][0].args, ('new message',))) >>> str(err) 'new message'
Assign
has built-in support for assigning to attributes of objects, keys of mappings (like dicts), and indexes of sequences (like lists). Additional types can be registered throughregister()
using the"assign"
operation name.Attempting to assign to an immutable structure, like a
tuple
, will result in aPathAssignError
. Attempting to assign to a path that doesn’t exist will raise aPathAccessError
.To automatically backfill missing structures, you can pass a callable to the missing argument. This callable will be called for each path segment along the assignment which is not present.
>>> target = {} >>> assign(target, 'a.b.c', 'hi', missing=dict) {'a': {'b': {'c': 'hi'}}}
Deletion¶
Delete attributes from objects and keys from containers.
- glom.delete(obj, path, ignore_missing=False)[source]¶
The
delete()
function provides “deep del” functionality, modifying nested data structures in-place:>>> target = {'a': [{'b': 'c'}, {'d': None}]} >>> delete(target, 'a.0.b') {'a': [{}, {'d': None}]}
Attempting to delete missing keys, attributes, and indexes will raise a
PathDeleteError
. To ignore these errors, use the ignore_missing argument:>>> delete(target, 'does_not_exist', ignore_missing=True) {'a': [{}, {'d': None}]}
For more information and examples, see the
Delete
specifier type, which this convenience function wraps.New in version 20.5.0.
- class glom.Delete(path, ignore_missing=False)[source]¶
In addition to glom’s core “deep-get” and
Assign
’s “deep-set”, theDelete
specifier type performs a “deep-del”, which can remove items from larger data structures by key, attribute, and index.>>> target = {'dict': {'x': [5, 6, 7]}} >>> glom(target, Delete('dict.x.1')) {'dict': {'x': [5, 7]}} >>> glom(target, Delete('dict.x')) {'dict': {}}
If a target path is missing, a
PathDeleteError
will be raised. To ignore missing targets, use theignore_missing
flag:>>> glom(target, Delete('does_not_exist', ignore_missing=True)) {'dict': {}}
Delete
has built-in support for deleting attributes of objects, keys of dicts, and indexes of sequences (like lists). Additional types can be registered throughregister()
using the"delete"
operation name.New in version 20.5.0.
Exceptions¶
- class glom.PathAssignError(exc, path, dest_name)[source]¶
This
GlomError
subtype is raised when an assignment fails, stemming from anassign()
call or otherAssign
usage.One example would be assigning to an out-of-range position in a list:
>>> assign(["short", "list"], Path(5), 'too far') Traceback (most recent call last): ... PathAssignError: could not assign 5 on object at Path(), got error: IndexError(...
Other assignment failures could be due to assigning to an
@property
or exception being raised inside a__setattr__()
.
- class glom.PathDeleteError(exc, path, dest_name)[source]¶
This
GlomError
subtype is raised when an assignment fails, stemming from andelete()
call or otherDelete
usage.One example would be deleting an out-of-range position in a list:
>>> delete(["short", "list"], Path(5)) Traceback (most recent call last): ... PathDeleteError: could not delete 5 on object at Path(), got error: IndexError(...
Other assignment failures could be due to deleting a read-only
@property
or exception being raised inside a__delattr__()
.