The package registry is still being built. The docs are live, everything else is a preview.

Edge Python

Sign In

Sign in to publish packages and pin them by sha256.


By continuing, you accept our Terms and Conditions.

@
Palette

Classes

Classes are state containers and namespaces, not the primary abstraction. This is a design choice. Two patterns:

  • State machines: a few methods that mutate the receiver.
  • Namespaces: a bundle of related functions and constants.

Supported:

  • Single and multiple inheritance (C3 MRO) with super().
  • @property / @x.setter.
  • @staticmethod and @classmethod.
  • A curated dunder protocol for operators, indexing, iteration, hashing, context managers, and attribute fallback (see Operator overloading and protocols).

Out of scope: descriptors, metaclasses, __slots__.

State-machine pattern

cmd + enter
3
Output

Namespace pattern

A class with no __init__ and no per-instance state is a namespace. Methods called on the class are unbound, with no self prepended.

cmd + enter
0
3.14159
25
27
Output

Inheritance and super()

Single or multiple bases (class Sub(Base):, class C(A, B):). Methods not on the subclass resolve along the C3 linearization (the MRO). An inconsistent hierarchy raises TypeError at class creation. isinstance(x, Base) walks the ancestor chain, so Sub instances are also instances of every ancestor.

super() (zero-arg) delegates to the next class up the chain, bound to the current self. Most common in __init__ to extend a base constructor.

cmd + enter
Rex (lab)
True
Output
cmd + enter
B
inconsistent hierarchy
Output

Attribute access on classes vs instances

Access formResolves to
MyClass.attrclass member, returned as-is (no binding)
MyClass.method()method called directly, no self
instance.attrinstance __dict__ first, then class
instance.method()bound method, self prepended

setattr / delattr work on instances and on class objects. The latter mutates the class’s members.

Class decorators

A class decorator is called with the class object and its return value binds to the name. It can add or replace class attributes (cls.kind = ...) or return a replacement.

cmd + enter
tagged
7
Output

Properties

@property turns a method into a read-only attribute. @x.setter makes it writable. Properties live on the class. Subclasses inherit and can override either side.

cmd + enter
20
68.0
212.0
Output

The two-argument form property(fget, fset) also works without decorator syntax.

Static methods

@staticmethod makes a method that receives no implicit self. It is a plain function that lives in the class namespace, callable as Class.method(...) or instance.method(...) with identical arguments. Subclasses inherit it and can override it. Use it for helpers that belong to a class conceptually but need no receiver.

cmd + enter
5
20.0
Output

The functional form staticmethod(func) also works without decorator syntax.

Class methods

@classmethod binds the class, not the instance, as the first argument. Accessed through a subclass, cls is the subclass, so alternate constructors return the right type down the hierarchy.

cmd + enter
1 2
Color Bright
Output

The functional form classmethod(func) also works without decorator syntax.

Operator overloading and protocols

Dunders (__add__, __eq__, __getitem__, …) plug a class into language protocols. Define them in the class body. The VM calls them when the matching operator, builtin, or syntax form runs.

cmd + enter
7
True
Output

Dunders are looked up on the class chain. The instance dict is skipped, so assigning obj.__add__ = ... has no effect. Subclasses inherit and may override.

Arithmetic

OperatorForwardReflected
a + b__add____radd__
a - b__sub____rsub__
a * b__mul____rmul__
a / b__truediv____rtruediv__
a // b__floordiv____rfloordiv__
a % b__mod____rmod__
a ** b__pow____rpow__
-a__neg__-
+a__pos__-

Return NotImplemented from the forward op to make the VM try the reflected op on the other operand. If both return NotImplemented (or neither is defined), the operation raises TypeError.

Subclass-first ordering applies here. When type(b) is a strict subclass of type(a), b.__radd__ runs before a.__add__. This lets a subclass override an inherited reflected op without touching the base.

cmd + enter
sub.__radd__
Output
cmd + enter
15
10
Output

Bitwise and shifts

The bitwise and shift operators follow the same forward/reflected protocol.

OperatorForwardReflected
a | b__or____ror__
a & b__and____rand__
a ^ b__xor____rxor__
a << b__lshift____rlshift__
a >> b__rshift____rrshift__
~a__invert__-

Comparison

OperatorForwardReflected
a == b__eq____eq__
a != b__ne____ne__
a < b__lt____gt__
a <= b__le____ge__
a > b__gt____lt__
a >= b__ge____le__

!= falls back to not __eq__ (coerced to bool) when __ne__ is absent. Every other comparison returns the dunder’s raw result. A __lt__ that returns 'A.lt' yields the string, not True.

cmd + enter
True
False
Output

Truth and length

bool(x) (and any boolean context) consults, in order:

  1. __bool__ if defined. It must return bool, else TypeError.
  2. __len__ if defined. False when the length is 0, else True.
  3. Default True.

len(x) calls __len__ directly. It must return a non-negative int.

cmd + enter
False
False True
5
Output

Indexing and containment

FormDunderArguments
obj[i]__getitem__(self, i)
obj[i] = v__setitem__(self, i, value)
del obj[i]__delitem__(self, i)
v in obj__contains__(self, value)

Slices pass as a slice object, so obj[1:3] calls __getitem__(self, slice(1, 3, None)). Indexes on built-in sequences coerce via __index__, including slice bounds. Dict keys never coerce.

Without __contains__, v in obj falls back to iterating obj and comparing with __eq__.

cmd + enter
1 missing
True False
Output

Iteration

MethodRole
__iter__Returns an iterator (often self).
__next__Returns the next item, or raises StopIteration to end the loop.
cmd + enter
[1, 2, 3]
True
Output

for loops, list(x), and tuple(x) all honour the protocol.

Callable

__call__ makes instances invocable. Positional and keyword arguments are forwarded like any method call.

cmd + enter
14
21
True
Output

Hashing

hash(x) calls __hash__. It must return an int, which is masked to INT_MAX.

Eq/hash invariant. A class that defines __eq__ without __hash__ is unhashable. hash(x) and {x: 1} raise TypeError. This prevents inconsistent dict keys.

cmd + enter
5
found
Output

Built-in dict and set compare instance keys by identity. A user __hash__ is returned by hash(), but does not change containment in built-in containers. Use the same instance reference to look up reliably.

Representation

Function / formDunderFallback
repr(x)__repr__<ClassName instance>
str(x), print(x)__str____repr__, then default
f"{x}" (no spec)__str__same as str(x)
f"{x:spec}"__format__built-in format spec engine
f"{x!r}"__repr__-

__format__(spec) receives the spec string and must return str. int(x) on an instance calls __int__, which is also used by %d / %x / %X / %o formatting. float(x) calls __float__ and falls back to __index__. abs(x) calls __abs__.

cmd + enter
P(3)
P(3)
P(3)
[P(3)]
Output

Attribute access fallback

__getattr__(self, name) runs only when normal lookup (instance dict, then class chain) misses. It receives the name as a string. Return the value, or raise AttributeError to surface a real miss.

cmd + enter
1
computed:anything
computed:foo
Output

Existing attributes bypass __getattr__. Only misses trigger it.

Context managers

with cm() as x: invokes __enter__. Its return value binds to as. On exit, __exit__(exc_type, exc_value, traceback) runs. The arguments are (None, None, None) on normal exit. On a raise, they carry the exception type and value, with traceback always None. A truthy return suppresses the exception. A falsy one propagates it.

cmd + enter
after
Output

Multiple managers (with a(), b() as x:) nest LIFO. b enters last and exits first. Each has its own implicit handler, so inner suppression still lets outer managers run their normal __exit__(None, None, None).

If __exit__ itself raises, the new exception replaces the original.

What’s not dispatched

Parsed for compatibility but never invoked on user classes:

  • __init_subclass__, __set_name__, descriptors (__get__ / __set__ / __delete__)
  • __new__. The VM constructs the instance and __init__ runs user logic.
  • Augmented-assignment dunders (__iadd__, …). a += b desugars to a = a + b, so __add__ covers it. Exception: list += extends in place (alias-visible). See Data types.
  • Async dunders (__aenter__ / __aexit__ / __aiter__ / __anext__). async with and async for use the sync paths. See Async.

What classes do not support

  • Metaclasses, descriptors (__get__ / __set__), __slots__, ABCs, __init_subclass__.
  • Async dunders, covered above.

Reuse behaviour through free functions and composition by default. Reach for inheritance and operator overloading when the abstraction genuinely calls for them.