- Surprises are more ugly than beautiful.
- -- loosely based on PEP 20
Python gotchas and surprising Python facts presented as lightning talk at the PyDays 2019. Inspired by the WAT lightning talk by Gary Bernhardt from CodeMash 2012. This repository contains links to the sources and all materials for the live presentation, as well as a PDF file with screenshots of the live demo.
The lightning talk was presented again at PyCon Austria 2025.
Recording on Youtube at PyCon Austria 2025:
Not really part of the lightning talk, but kind of related and also collected and prepared for the PyDays 2019, some mind screwing Python riddles with surprising solutions. Riddles are available as PDF and SVG.
Talks about crazy facts in other programming languages than Python:
Mind screwing Python code snippets:
- https://github.com/satwikkansal/wtfpython
- https://www.codementor.io/satwikkansal/some-tricky-python-snippets-that-may-bite-you-off-bhndh45zp
- https://kate.io/blog/2017/08/22/weird-python-integers/
- https://dbader.org/blog/python-mystery-dict-expression
- https://blog.brush.co.nz/2008/01/ten-python-quirkies/
- https://github.com/qezz/python-common-gotchas
- https://www.toptal.com/python/top-10-mistakes-that-python-programmers-make
- https://gist.github.com/brianspiering/6921253524fe0a058d4de8aa0d306c02
- https://www.geeksforgeeks.org/a-b-assignment-riddle-in-python/
- https://www.geeksforgeeks.org/python-a-b-is-not-always-a-a-b/
To type all the Unicode characters, one can cheat a bit by using doitlive. The IPython support is great, but there seems to be a dependency hell. One needs prompt-toolkit==1.x and 5.0<=IPython<7.0.
To install with conda:
$ conda env update -f env-frozen.yml
$ conda activate ugly-surprises
$ cd presentation
$ PYTHONPATH=$(pwd)/.. doitlive play -q presentation-part2-unicode.shIn 2025 pixi has been used instead of conda:
$ pixi shell
$ doitlive play -q presentation-part2-unicode.shThe automatic shell completion can be disruptive, so it is disabled by adding the following
lines to ~/.ipython/profile_default/ipython_config.py:
c = get_config() #noqa
c.TerminalInteractiveShell.autosuggestions_provider = NoneA warning is displayed by doitlive when using gnome-terminal. Everything works as intended despite this warning, but neither attempts to filter it out nor switching to a different terminal emulator removes the message. Therefore, the warning is disabled by modifying the source code in the .pixi environment:
--- .pixi/envs/default/lib/python3.10/site-packages/prompt_toolkit/application/application.py
+++ .pixi/envs/default/lib/python3.10/site-packages/prompt_toolkit/application/application.py-patched
@@ -1238,9 +1238,9 @@
return # We know about this already.
def in_terminal() -> None:
- self.output.write(
- "WARNING: your terminal doesn't support cursor position requests (CPR).\r\n"
- )
self.output.flush()
run_in_terminal(in_terminal)See notes.rst for detailed content of the presentation. The code that needs to be typed can be found in presentation-part1.sh and presentation-part2-unicode.sh.
8 workspaces need to be prepared:
- Screen 1: eog white.png
- Screen 2: eog ugly-surprise.jpg
- Screen 3: eog ugly-surprise-with-title.png
- Screen 4: ipython or doitlive play -q presentation-part1.sh
- Screen 5: doitlive play -q presentation-part2-unicode.sh
- Screen 6: vi mandelbrot.py
- Screen 7: mandelbrot.png
- Screen 8: mandelbrot-with-text.png
The presentation is done by switching from one workspace screen to the next one. Screen 4 can be typed live or by using doitlive. Screen 5 contains unicode characters, so one needs to use doitlive.
The slides/slides.pdf contains screenshots of the live presentation, which can be used as a backup.
Numpy seems to use partial pairwise summation in some cases, which can lead to different results depending on the data type used:
>>> import numpy as np
>>> data = [0.042411500823462206, 0.5387831400906496,
2.0907299109640074, 0.012566370614359173, 0.5387831400906496,
0.10053096491487339, 0.5387831400906496, 0.10053096491487339,
0.8042477193189871, 0.1963495408493621, 1.1451105222334796,
1.1451105222334796]
>>> np.sum(np.array(data, dtype=object)) - np.sum(np.array(data, dtype=float))
8.881784197001252e-16Interesting mistakes and surprises without Python: