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 returns p.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

pythonsyntactic-sugarcomputer-graphicsdata structures