desugar
Unravelling Python's syntactic sugar source code.
There are accompanying blog posts to go with all of the code in this repository.
Unravelled syntax
obj.attr➠builtins.getattr(obj, "attr")(includingobject.__getattribute__())a + b➠operator.__add__(a, b)a - b➠operator.__sub__(a, b)a * b➠operator.__mul__(a, b)a @ b➠operator.__matmul__(a, b)a / b➠operator.__truediv__(a, b)a // b➠operator.__floordiv__(a, b)a % b➠operator.__mod__(a, b)a ** b➠operator.__pow__(a, b)a << b➠operator.__lshift__(a, b)a >> b➠operator.__rshift__(a, b)a & b➠operator.__and__(a, b)a ^ b➠operator.__xor__(a, b)a | b➠operator.__or__(a, b)a += b➠a = operator.__iadd__(a, b)a -= b➠a = operator.__isub__(a, b)a *= b➠a = operator.__imul__(a, b)a @= b➠a = operator.__imatmul__(a, b)a /= b➠a = operator.__itruediv__(a, b)a //= b➠a = operator.__ifloordiv__(a, b)a %= b➠a = operator.__imod__(a, b)a **= b➠a = operator.__ipow__(a, b)a <<= b➠a = operator.__ilshift__(a, b)a >>= b➠a = operator.__irshift__(a, b)a &= b➠a = operator.__iand__(a, b)a ^= b➠a = operator.__ixor__(a, b)a |= b➠a = operator.__ior__(a, b)~ a➠operator.__invert__(a)- a➠operator.__neg__(a)+ a➠operator.__pos__(a)a == b➠operator.__eq__(a, b)(includingobject.__eq__())a != b➠operator.__ne__(a, b)(includingobject.__ne__())a < b➠operator.__lt__(a, b)a <= b➠operator.__le__(a, b)a > b➠operator.__gt__(a, b)a >= b➠operator.__ge__(a, b)a is b➠operator.is_(a, b)a is not b➠operator.is_not(a, b)not a➠operator.not_(a)a in b➠operator.__contains__(b, a)a not in b➠operator.not_(operator.__contains__(b, a))a or b➠_temp if (_temp := a) else ba and b➠_temp if not (_temp := a) else bimport a.b➠a = __import__('a.b', globals(), locals())import a.b as c➠c = __import__('a', globals(), locals(), ['b'], 0).bfrom .a import b➠b = __import__('a', globals(), locals(), ['b'], 1).bfrom .a import b as c➠c = __import__('a', globals(), locals(), ['b'], 1).bassert ...➠ see below (post)for ...➠ see below (includingbuiltins.iter()andbuiltins.next())pass➠"pass"with ...➠ see below (post)async def ...➠ see below (post)await ...➠desugar.builtins._await(...)async for➠ see below (includingbuiltins.aiter()andbuiltins.anext())async with➠ see below (post)[c for b in a]➠list(c for b in a){c for b in a}➠set(c for b in a){c: d for b in a}➠dict((c, d) for b in a)[a, b]➠list((a, b))(includes iterable unpacking){a, b}➠set((a, b))(includes iterable unpacking)(a, b)) ➠(lambda *args: args)(a, b)(includes iterable unpacking){a: b, c: d}) ➠dict(((a, b), (c, d)))(include dictionary unpacking)
assert ...
With message
assert a, b➠
if __debug__:
if not a:
raise AssertionError(b)Without a message
assert a➠
if __debug__:
if not a:
raise AssertionErrorfor ...
Without else
for a in b:
c➠
_iter = iter(b)
while True:
try:
a = next(_iter)
except StopIteration:
break
else:
c
del _iterWith else
for a in b:
c
else:
d➠
_iter = iter(b)
_looping = True
while _looping:
try:
a = next(_iter)
except StopIteration:
_looping = False
continue
else:
c
else:
d
del _iter, _loopingwith ...
with a as b:
c➠
_enter = type(a).__enter__
_exit = type(a).__exit__
b = _enter(a)
try:
c
except:
if not _exit(a, *sys.exc_info()):
raise
else:
_exit(a, None, None, None)async def ...
async def spam():
...➠
@types.coroutine
def spam():
...async for ...
Without else
async for a in b:
c➠
_iter = aiter(b)
while True:
try:
a = await anext(_iter)
except StopAsyncIteration:
break
else:
c
del _iterWith else
async for a in b:
c
else:
d➠
_iter = aiter(b)
_looping = True
while _looping:
try:
a = await anext(_iter)
except StopAsyncIteration:
_looping = False
continue
else:
c
else:
d
del _iter, _loopingasync with ...
async with a as b:
c➠
_enter = type(a).__aenter__
_exit = type(a).__aexit__
b = await _enter(a)
try:
c
except:
if not await _exit(a, *sys.exc_info()):
raise
else:
await _exit(a, None, None, None)Syntax to (potentially) unravel
Keywords
Taken from the keyword module.
Expressions
Statements
-
class~
Tokens
Taken from the token module.
-
[]for subscriptions (get, set, del),:for slicing * -
()for generator expressions (and why they can't be unravelled) -
()for calls -
@for decorators * -
, -
;* -
...*
Literals
The list below ignores literals which are represented via syntax above.
For instance, lists are ignored as they are represented by [] tokens.
NoneFalseTrue- Bytes (
b,r) - Strings (
u,f,r; single line, multi-line) * - Integers (base-10,
b,o,x) - Floats (point,
e) - Complex/imaginary numbers

