# pydoc > pyrsistent

---
type: CommandReference
command: pyrsistent
mode: pydoc
section: package
source: pydoc3
---

## Quick Reference

- `m(a=1, b=2)` — create persistent map
- `v(1, 2, 3)` — create persistent vector
- `s(1, 2, 3)` — create persistent set
- `pvector([1, 2, 3])` — create persistent vector from iterable
- `pmap({'a': 1})` — create persistent map from dict
- `pset([1, 2, 3])` — create persistent set from iterable
- `l(1, 2, 3)` — create persistent list (plist)
- `dq(1, 2, 3)` — create persistent deque
- `b(1, 2, 3, 2)` — create persistent bag
- `freeze([1, {'a': 3}])` — recursively convert to persistent structures
- `thaw(s(1, 2))` — recursively convert back to Python builtins
- `get_in(keys, coll, default=None)` — nested access
- `field()` — declare field for PRecord/PClass

## Name

pyrsistent — Persistent/immutable data structures for Python

## Synopsis

python
import pyrsistent
from pyrsistent import pmap, m, pvector, v, pset, s, plist, l, pdeque, dq, pbag, b, freeze, thaw, get_in, field, PRecord, PClass, CheckedPMap, CheckedPVector, CheckedPSet, ImmutableException, InvariantException, CheckedKeyTypeError, CheckedValueTypeError, ny, rex, inc, discard, mutant, optional
## Classes

### `PMap` — persistent map/dict
- Implements `Mapping`, `Hashable`, dot-notation access.
- `set(key, val)` — return new map with key-value inserted
- `remove(key)` — return new map without key (raises `KeyError`)
- `discard(key)` — return new map without key, returns self if missing
- `update(*maps)` — merge maps (rightmost wins)
- `update_with(fn, *maps)` — merge with custom function
- `transform(*transformations)` — apply transformations on nested structures
- `evolver()` — mutable view for batch updates
- `get(key, default=None)`, `keys()`, `values()`, `items()`, `iterkeys()`, `itervalues()`, `iteritems()`
- `copy()`, `__add__`, `__or__`, `__contains__`, `__eq__`, `__hash__`, `__getitem__`, `__getattr__`, `__len__`, `__iter__`
- Complexity: `O(log32(n))` for access/insert

### `PRecord` — PMap with fixed fields
- Inherits `PMap`, `CheckedType`
- `set(*args, **kwargs)` — atomic update of multiple fields
- `serialize(format=None)` — serialize with custom serializers
- `create(kwargs, _factory_fields=None, ignore_extra=False)` — class method factory
- `evolver()` — returns record evolver

### `CheckedPMap` — PMap with type and invariant checks
- Subclass with `__key_type__`, `__value_type__`, `__invariant__` (lambda `(k, v): (bool, msg)`)
- `create(source_data, _factory_fields=None)`, `evolver()`, `serialize(format=None)`
- Example: `class IntToFloatMap(CheckedPMap): __key_type__ = int; __value_type__ = float; __invariant__ = lambda k, v: (int(v) == k, 'Invalid mapping')`

### `PVector` — persistent vector (list-like)
- Implements `Sequence`, `Hashable`, `__getitem__` with slicing
- `append(val)`, `extend(obj)`, `set(i, val)` — return new vector
- `mset(*args)` — multi-set: `v.mset(0, 11, 2, 33)`
- `delete(index, stop=None)`, `remove(value)`, `count(value)`, `index(value, *args)`
- `evolver()` — mutable view
- `transform(*transformations)`
- `__add__`, `__mul__`, `__len__`, `__hash__`
- Complexity: `O(log32(n))` access, amortized `O(1)` append

### `CheckedPVector` — PVector with type and invariant checks
- Subclass with `__type__` and `__invariant__`
- `append`, `extend`, `set`, `evolver`, `serialize`, `create`

### `PClass` — plain Python object with fixed fields, not a collection
- Subclass with `field()` declarations
- `set(*args, **kwargs)`, `remove(name)`, `transform(*transformations)`, `evolver()`, `serialize(format=None)`
- `create(kwargs, _factory_fields=None, ignore_extra=False)`

### `PDeque` — persistent double-ended queue
- `append(elem)`, `appendleft(elem)`, `pop(count=1)`, `popleft(count=1)`, `extend(iterable)`, `extendleft(iterable)`
- `rotate(steps)`, `reverse()`, `remove(elem)`, `count(elem)`, `index(value, start=0, stop=None)`
- Properties: `left`, `right`, `maxlen`
- Supports `maxlen` for bounded queue
- `__getitem__`, `__len__`, `__hash__`, `__reversed__`

### `PSet` — persistent set
- Implements `Set`, `Hashable`
- `add(element)`, `remove(element)`, `discard(element)`, `update(iterable)`, `copy()`
- `difference`, `intersection`, `union`, `symmetric_difference`, `isdisjoint`, `issubset`, `issuperset`
- `evolver()`
- Complexity: `O(log32(n))`

### `CheckedPSet` — PSet with type and invariant checks
- Subclass with `__type__` and `__invariant__`
- `add`, `remove`, `evolver`, `serialize`, `create`

### `PBag` — persistent bag/multiset (unordered, allows duplicates)
- `add(element)`, `remove(element)`, `update(iterable)`, `count(element)`
- `__add__` (union with duplicates), `__sub__` (remove one occurrence per element), `__and__` (intersection, min count), `__or__` (union, max count)
- `__iter__`, `__len__`, `__hash__`, `__contains__`, `__eq__`

### `PList` — classical Lisp-style singly linked list
- `cons(elem)`, `mcons(iterable)`, `remove(elem)`, `reverse()`, `split(index)`, `count(value)`, `index(value, start, stop)`
- Properties: `first`, `rest`
- `__getitem__`, `__len__`, `__hash__`, `__eq__`
- Complexity: `O(k)` access, `O(1)` cons

### `PClassMeta` — metaclass for PClass (internal)

### Exception classes

- `InvariantException(error_codes=(), missing_fields=(), *args, **kwargs)` — raised when invariant tests fail or mandatory field missing
- `CheckedTypeError(source_class, expected_types, actual_type, actual_value, *args, **kwargs)` — base for type errors
- `CheckedKeyTypeError` — key type mismatch
- `CheckedValueTypeError` — value type mismatch
- `CheckedType` — marker class for creation and serialization of checked object graphs

## Functions

- `pmap(initial={}, pre_size=None)` — create persistent map from dict
- `m(**kwargs)` — create persistent map from keyword arguments
- `pvector(iterable)` — create persistent vector from iterable
- `v(*args)` — create persistent vector from arguments
- `pset(iterable)` — create persistent set from iterable
- `s(*args)` — create persistent set from arguments
- `plist(iterable, reverse=False)` — create persistent list from iterable
- `l(*args)` — create persistent list from arguments
- `pdeque(iterable, maxlen=None)` — create persistent deque
- `dq(*args)` — create persistent deque from arguments
- `pbag(iterable)` — create persistent bag from iterable
- `b(*args)` — create persistent bag from arguments
- `freeze(obj, strict=True)` — recursively convert Python containers to pyrsistent (list→pvector, dict→pmap, set→pset, tuple→tuple)
- `thaw(obj, strict=True)` — recursively convert pyrsistent containers back to Python builtins
- `get_in(keys, coll, default=None, no_default=False)` — nested access; returns `coll[i0]...[iX]`, raises `KeyError`/`IndexError` if `no_default=True`
- `field(type=None, invariant=None, initial=None, mandatory=False, factory=None, serializer=None)` — field specification for PRecord/PClass
- `pmap_field(key, value, optional=False, invariant=None)` — create checked PMap field
- `pvector_field(item_type, optional=False, initial=None)` — create checked PVector field
- `pset_field(item_type, optional=False, initial=None)` — create checked PSet field
- `immutable(fields, name='Point')` — create a named-tuple based persistent class with optional frozen members (trailing underscore)
- `mutant(fn)` — decorator that freezes all arguments and return value
- `ny` — matcher that matches any value (for `transform`)
- `rex(pattern)` — regular expression matcher for `transform`
- `inc(value)` — add one to value
- `discard(element, structure)` — discard element from structure
- `optional(typs)` — specify that a value may be `None` or any of `typs`

## Examples

### Creating persistent structures

python
from pyrsistent import m, v, s, l, dq, b, pmap, pvector, pset, plist, pdeque, pbag
m1 = m(a=1, b=2)
v1 = v(1, 2, 3)
s1 = s(1, 2, 3, 2)
l1 = l(1, 2, 3)
dq1 = dq(1, 2, 3)
b1 = b(1, 2, 3, 2)
pmap1 = pmap({'a': 1, 'b': 2})
pvector1 = pvector([1, 2, 3])
pset1 = pset([1, 2, 3, 2])
plist1 = plist([1, 2, 3])
pdeque1 = pdeque([1, 2, 3], maxlen=5)
pbag1 = pbag([1, 2, 3, 2])
### Using PMap

python
m1 = m(a=1, b=2)
m2 = m1.set('c', 3)
m3 = m2.remove('a')
# m3 == {'b': 2, 'c': 3}
m3['c']  # 3
m3.c     # 3 (dot notation)
### Using PVector

python
p = v(1, 2, 3)
p2 = p.append(4)
p3 = p2.extend([5, 6, 7])
p3[5]  # 6
p.set(1, 99)  # pvector([1, 99, 3])
p.delete(1, 3)  # pvector([1, 4, 5])
p.mset(0, 11, 2, 33)  # pvector([11, 2, 33])
### Using PDeque

python
x = pdeque([1, 2, 3])
x.left   # 1
x.right  # 3
x.pop()  # pdeque([1, 2])
x.popleft()  # pdeque([2, 3])
x.append(4)  # pdeque([1, 2, 3, 4])
y = pdeque([1, 2, 3], maxlen=3)
y.append(4)  # pdeque([2, 3, 4], maxlen=3)
### Using PSet

python
s1 = s(1, 2, 3)
s2 = s1.add(4)
s3 = s2.remove(2)  # pset([1, 3, 4])
s1.update([3, 4, 4])  # pset([1, 2, 3, 4])
### Using PBag

python
bag = pbag([1, 2, 3, 1])
bag.count(1)  # 2
bag.add(4)    # pbag([1, 1, 2, 3, 4])
bag.remove(1) # pbag([1, 2, 3, 4])
### Using PList

python
x = plist([1, 2])
y = x.cons(3)  # plist([3, 1, 2])
y.first  # 3
y.rest == x  # True
y[:2]  # plist([3, 1])
plist([1, 2, 3, 4]).split(2)  # (plist([1, 2]), plist([3, 4]))
### freeze and thaw

python
from pyrsistent import freeze, thaw
freeze([1, {'a': 3}])  # pvector([1, pmap({'a': 3})])
freeze((1, []))  # (1, pvector([]))
thaw(s(1, 2))    # {1, 2}
thaw(v(1, m(a=3)))  # [1, {'a': 3}]
### get_in

python
from pyrsistent import freeze, get_in
transaction = freeze({'name': 'Alice', 'purchase': {'items': ['Apple', 'Orange'], 'costs': [0.50, 1.25]}})
get_in(['purchase', 'items', 0], transaction)  # 'Apple'
get_in(['purchase', 'total'], transaction)  # None
get_in(['purchase', 'total'], transaction, 0)  # 0
### transform

python
from pyrsistent import freeze, ny
news_paper = freeze({'articles': [{'author': 'Sara', 'content': 'A short article'}, {'author': 'Steve', 'content': 'A slightly longer article'}], 'weather': {'temperature': '11C', 'wind': '5m/s'}})
short_news = news_paper.transform(['articles', ny, 'content'], lambda c: c[:25] + '...' if len(c) > 25 else c)
### Evolver

python
v1 = v(1, 2, 3, 4, 5)
e = v1.evolver()
e[1] = 22
e.append(6)
e.extend([7, 8, 9])
e[8] += 1
v2 = e.persistent()  # pvector([1, 22, 3, 4, 5, 6, 7, 8, 10])
### Checked types

python
class Positives(CheckedPVector):
    __type__ = (int, float)
    __invariant__ = lambda n: (n >= 0, 'Negative')
Positives([1, 2, 3])  # Positives([1, 2, 3])

class IntToFloatMap(CheckedPMap):
    __key_type__ = int
    __value_type__ = float
    __invariant__ = lambda k, v: (int(v) == k, 'Invalid mapping')
IntToFloatMap({1: 1.5, 2: 2.25})  # IntToFloatMap({1: 1.5, 2: 2.25})
### PRecord and PClass with field

python
from pyrsistent import PRecord, field, PClass, CheckedTypeError

class MyRecord(PRecord):
    x = field(type=int, mandatory=True)
    y = field(type=str, initial='default')

r = MyRecord(x=1)
r.set(x=2, y='new')  # MyRecord(x=2, y='new')

class MyClass(PClass):
    x = field()
    y = field()

a = MyClass(x=1)
a.set(x=2)  # MyClass(x=2, y=None)
## See Also

- [pyrsistent on GitHub](https://github.com/tobgu/pyrsistent)