If you code long enough with any language, there are things you will eventually wish to tweak. As of 2023, those are mine:
-
Adding
?
as aKeyError
,IndexError
andAttributeError
operator. -
Give more visibility to
partial()
-
Kill implicit string concatenation
-
Make
iter[]
andcallable[]
type hint generics -
Introduce a
Path
literal -
Adding a
.get()
method tolist
-
Providing unpacking for dicts
-
Making
itertools
slice
,takewhile
anddropwhile
syntax. -
Add lazy imports and calculations
-
Provide a mechanism for export in modules
-
Turn the generator declaration into something more explicit
-
Add exception declaration to type hints
June might be a bit early for making a list of things I wish to get into Python one day, but to my defense, I have been a very good boy.
Please note that this article will have little influence on anything, and that it’s mostly cathartic. I update it in my head every 3 months or so, sometimes you just gotta write it down. It’s also an excuse to review features and patterns and share them with you. I’ll use all the tricks to motivate you to come back reading.
But all of them are a possibility, it’s not something that would change the language to the point of destroying its philosophy or style. I’m not talking about multi-line lambdas or copy-on-write immutable data structures here. Maybe breaking compat. Just a little bit.
Yes, that’s the title.
I wish for an ?
operator. And the complementary ?.
and ?[
that come with it.
Indeed, in many languages, ?
allows me to say “if something is null or unset, use this other thing”.
E.G, in JS, you can do:
const count = start ?? 5;
If will set count
to start
if it exists, or use 5
if it doesn’t. Unlike ||
, it will work with start
being 0
as well.
But the best feature is the null handling when traversing data structures like:
some.deeply?.nested?.thing() ?? "default value"
This will call thing()
only if the whole chain exists, or use the default value. No need to handle errors.
Now in Python, None
handling would not be as useful as having ?[
catch KeyError
and IndexError
while ?.
would catch AttributeError
:
some?.deeply?["thing"] ?? "default value"
And that would be super sweet.
I like functools.partial()
. It’s a nice, explicit way to prefill arguments for a function:
>>> from functools import partial >>> from_hex = partial(int, base=16) # prefill int "base" param to be 16 >>> from_hex("FA") # now I got a new hexadecimal converter function 250
It’s more explicit than lambda
, you see partial()
, you know what’s going on. Plus the repr()
tells you what happens:
>>> from_hex functools.partial(
, base=16)
Not to mention it’s faster than a lambda.
But partial()
it is not very popular in the community, in fact, a lot of devs don’t even know about it.
That’s because it’s hidden behind an import. To be honest, even I am too lazy to import it sometimes.
Santa, I wish for partial()
to become a built-in.
And given it’s unlikely because adding built-ins are a pain in the butt for the core devs, at least we could make it a method on all callables.
That would look so nice:
>>> from_hex = int.partial(base=16)
The language doesn’t have currying, so that would compensate for that. And give visibility to a very nice feature.
This is a sin:
>>> "a" "b" == "ab" True
It’s handy for long strings, I get it. I use it:
>>> ("This is long" ... " yet on one line")
But it’s not worth the bugs people introduce by mistake. Every year I get one.
If you have the same problem, pylint can help, because PEP 3126 couldn’t.
When list
, tuple
and dict
became capable of expressing generics in 3.9, we moved from the horror show of:
from typing import List, Tuple, Optional ... Optional[Union[List[int], Tuple[int]]] ...
To:
... list[int] | tuple[int] | None ...
And that made typing suddenly bearable.
But there are two things that are still common and a pain to declare: iterables and callables.
Having to import them every time is a chore:
from typing import Iterable, Callable def bullets_points(elements: Iterable[str], formattter: Callable[[str, str], str]): ...
Since we have already iter()
and callable()
as built-in, I would love to be able to do:
def bullets_points(elements: iter[str], formattter: callable[[str, str], str]): ...
In the last few years, there has been a great focus on improving the Python industrialization story: adding an event loop, type hints, improving speed, etc.
Of course, there is a limited budget of time, skills and resources, so this means the scripting story of Python has not moved as much as it used to.
pathlib
and f-string
were the last great scripting goodies that were added to Python, and it was in 3.6.
pathlib.Path
suffers from the import syndrome: because you ha