In Rust, this would be a compile-time error instead. Sadly, here we have to (or rather, should) include the annoying assert False branches so that the function crashes A typicalĮxample is returning multiple values (or a single complex value) from a function. The second step is actually making these interfaces as exact and “locked down” as possible. Using type hints is one thing, but that merely describes what is the interface of your functions. Dataclasses instead of tuples or dictionaries Strings or a dictionary mapping strings to integers, it can be a sign that you might want to And if it does happen, it canĪctually signal a problem with the code – if your function parameter can be a number, a tuple of In my experience, this situation does not happen that often. Now, I’m not a sith absolutist in this regard, and if it takes five nested type hints toĭescribe a single parameter, I will usually just give up and give it a simpler, albeit imprecise In what is Item, I can just use Go to definition and immediately see how does that type look like. Unlike a doc comment, which can get easily out of date when the code changes, when I change the typesĪnd don’t update the callers of the function, the typechecker will yell at me 1. With the signature above, I can get a pretty good idea how can I use theįunction, what to pass it as arguments, and what can I expect to be returned from it. Writing out the types explicitly forces me to think about what will be the actual interface providedīy the function, and how can I make it as strict as possible, to make it hard for its callers to Is bottlenecked by the number of characters I write per minute, and that doesn’t really happen. When I read a function signature looking like this:ĭef find_item ( records : List, check : Callable, bool ] ) -> Optional :ĭid it take me more time to write the signature? Yes. The first and foremost thing is using type hints where possible, particularly in function Presented ideas were all invented in Rust, they are also used in other languages, of course. Rather than attempts to promote some universal truths :) Also, I’m not claiming that the “IMHO” to every sentence, so take everything in this post as simply my opinions on the matter, Note: this post contains a lot of opinions about writing Python code. It’s no rocket science, but I still felt like it might be useful to document them. In this post I’ll show a few examples of such patterns applied to Python My experience, this approach leads to programs that are easier to understand and change. Mostly because in my experience, the latter quite often turn into the former :) In I try to do this both for programs that will be maintained for a while, but also for oneshot It basically boils down to two things - using type hints as much as possible, and upholding Program, but if you use a type checker (like pyright) orĪn IDE with a type analyzer (like P圜harm), you can still get a similar level of quick feedback about aĮventually, I started adopting some concepts from Rust in my Python programs. In Python, you can still execute such incorrect Interface will usually cause a compilation error. To misuse and thus prevent undefined behaviour and various bugs. To be clear, by “guarantees” I don’t mean memory safety here (Python is reasonably memory safeĪs-is), but rather “soundness” – the concept of designing APIs that are very hard or outright impossible Wasn’t provided with the same guarantees. Prevents “by construction”, I suddenly became quite anxious whenever I got back to Python and However, afterĮxperiencing the strictness of the Rust type system, and noticing all the problems that it Returning dictionaries everywhere, and occasionally falling back Usually writing Python code in a very dynamic and type-loose way, without type hints, passing and Programs in other programming languages, most notably in Python. I started programming in Rust several years ago, and it has gradually changed the way I design
0 Comments
Leave a Reply. |