* Replacing literals with variables and named constants
* Replacing literals with regexes
* Replacing literals with function calls
* Replacing literals with set membership tests
We draw key learning points from real #Python applications:
* Datetime formatting mini language
* Language tokenizer
* SQL logic for JSON lines
* SQL logic for two level JSON
* Traversing arbitrary depth JSON trees
* Marshal style data serializer
There is a problems and solutions section:
* Inverting case logic
* Matching sets and frozensets
* Exact type matches
* Order of overlapping cases
* Converting hasattr() duck typed cases
* Handling difficult cases
* Fooling aggressive linters
* Floating point special values
I'll post a link to the presentation video when it is available, but I only had 30 minutes.
Perhaps another conference has an open back to back timeslots for 60 to 75 minutes.
This is a super interesting topic.
#Python 's Structural pattern matching is amazing.
But when you apply it to real world code, all kinds of interesting problems arise and the solutions aren't always obvious.
The PDF isn't pretty. My slides are generated by Sphinx in a read-tuhe-docs format. When I get a chance (and figure-out how), I'll post the beautiful version of the slides on Github pages.
Hopefully, by then I'll have a video link to post as well.
#Python tip: The default_factory feature of a defaultdict is only useful when building up a dictionary (automatically adding missing keys).
However, that feature is a menace when doing lookups (risking accidental dict mutation).
Consider converting back to a regular dict.
1/
# During build-up, we want the factory magic.
d = defaultdict(list)
for elem in data:
d[feature(elem)].append(elem)
# Magic is no longer useful.
d = dict(d)
# Lookups are now safe.
print(d[some_feature])
2/
Converting back to a regular dictionary is cheap.
The hash values are reused rather than recomputed. The new dict is presized in a single step. The key and value pointers are copied rather than inserted. The only slow part is updating all the reference counts.
3/
#Python news: It was always awkward to write a type annotation for methods that returned self (an instance of the current class). As of yesterday, typing.Self was added to make this much easier and more readable.
We are often burdened by preconceived ideas, ideas that we invented, acquired on related projects, or heard about in class. Sometimes we undertake a project in order to try out a favorite idea. Such ideas may not be derived from our requirements by a rational process -— Parnas
This thought is equally interesting if you switch the judgment from "burdened" to "empowered".
Either way, the core idea remains than programs have a human dimension that transcends requirements and "rational design".
Argh! Who thought Black should be automatically applied to lines in the IPython CLI?
The makes it less useful for education purposes, less useful for interactive math, and annoying when it rewrites your input across multiple lines.
In a #Python course, if you want to demonstrate that print('hello') and print("hello") are the same, then too bad. The CLI rewrites both to use double quotes and the students can't see what you were demonstrating.
When doing math, you improve readability by grouping your terms as shown in PEP 8:
3*x**2 - 5*x + 10
However, the new #Ipython CLI immediately expands it to:
#Python success: I was finally able to make a type annotated pure python version of max().
All it took was a protocol bound to a typevar, a custom sentinel class, unions, overloads, isinstance checks, casts, repeated arguments, and the / and * notation.