Swizzle: Manipulate multiple attributes in Python at once
Introduction
Swizzle is a tiny Python package that lets you manipulate multiple attributes on an object at once. You can theoretically chain these attribute accesses indefinitely:
v.xyz.yzx.xxy # pulls attributes in whatever wild combination you want
You can reorder, duplicate, or mix attributes however you like, all using simple dot notation. These examples are simple, but you can actually swizzle combinations of attribute names of any length.
How Swizzle works
When you access an attribute, Swizzle first tries a normal lookup via Python’s __getattribute__
or user-defined __getattr__
. If that lookup fails, it treats the attribute name as a sequence of existing attributes and returns their values in that order.
If an object p
has x
and y
:
p.x
returnsp.x
p.yx
returns(p.y, p.x)
Custom separators and class-level swizzling
You can customize the separator between attribute names to make swizzle expressions visually clearer and easier to distinguish, especially when dealing with overlapping or common attribute names.
import swizzle
@swizzle(sep='_')
class Vector:
def __init__(self, x, y, z, w):
self.x, self.y, self.z, self.w = x, y, z, w
v = Vector(1, 2, 3, 4)
print(v.x_y_z_w) # Vector(x=1, y=2, z=3, w=4)
You can also enable swizzling on class-level attributes (not just instances) by passing meta=True
, which is particularly useful for enums:
from enum import IntEnum
import swizzle
@swizzle(meta=True)
class Axis(IntEnum):
X = 1
Y = 2
Z = 3
print(Axis.YXZ) # Axis(Y=<Axis.Y: 2>, X=<Axis.X: 1>, Z=<Axis.Z: 3>)
Setting multiple attributes at once
Swizzle supports setting multiple attributes in one go using the same swizzle syntax:
import swizzle
@swizzle(setter=True)
class Vector:
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
v = Vector(1, 2, 3)
print(v.yzx) # Vector(y=2, z=3, x=1)
v.zyx = 9, 8, 7
print(v.zyx) # Vector(z=9, y=8, x=7)
Tip: When using setters, it might make sense to use __slots__
or a custom sep
to avoid introducing new unintended attributes due to swizzling typos.
Swizzled tuples and chaining power
By default, Swizzle produces a swizzledtuple
, which is a swizzled spin-off of Python’s namedtuple
. This allows you to chain swizzle expressions theoretically forever:
from swizzle import swizzledtuple
Vector = swizzledtuple('Vector', 'x y z')
v = Vector(1, 2, 3)
print(v.yzx) # Vector(y=2, z=3, x=1)
v1 = v.yzx # swizzle output stored separately
v2 = v1.xxzyzz # swizzle the output again
print(v2) # Vector(x=1, x=1, z=3, y=2, z=3, z=3)
If you prefer plain tuples instead, you can set type=tuple
in the decorator. But chaining is only supported with swizzledtuple
.
You can install it via:
pip install swizzle
and check out the repo here: github.com/janthmueller/swizzle