These last years I've already written a couple of posts [1] and [2] putting together some Python tricks that I had been collecting over my development. It's time to put together a few more.
1) I've recently come up with another interesting use case of the walrus operator (aka assignment expression) that I can add to my list here, initializing an object (invoke constructor, dictionary literal) with values that depend ones on others, I mean:
a = 4
b = 8
d1 = {
"f1": (aux := a + b),
"f2": aux + 4
}
d1
Out[7]: {'f1': 12, 'f2': 16}
A long time ago I posted about some JavaScript techniques for this kind of initialization.
2) Unpacking/destructuring is such a nice Python feature, and while not so rich as its JavaScript counterpart, there are still non trivial cases, like unpacking nested structures.
a, [b, c], d = ["aa", ["bb", "cc"], "dd"]
print(a, b, c, d)
# aa bb cc dd
I recently used it combined with enumerate and zip, which makes a pretty nice example:
names = ['Alice', 'Bob', 'Charlie']
ages = [24, 50, 18]
for i, (name, age) in enumerate(zip(names, ages)):
print(i, name, age)
# 0 Alice 24
# 1 Bob 50
# 2 Charlie 18
3) When applying a decorator to a function, the decorator function can be any expression, which allows us odd constructs like conditional decorators:
def deco1(fn): return fn
def deco2(fn): return None
do_crash = False
@(deco1 if not crash else deco2)
def do_print(a):
print(a)
do_print("aaa")
# aaa
4) Sometimes you need a "do nothing" function (like a sort of Null Object Pattern, but for functions). The fit it all implementation, that works with any number of positional or keyword arguments, is:
def do_nothing(*ars ,**kwargs):
pass
5) Immediately Invokable Functions (IIFE's) are quite a thing in JavaScript. In Python we can immediately invoke a lambda expression, but as lambdas can not contain statements, there's no way to immediately invoke a function with statements. Well, there is indeed, using a decorator, a decorator that instead of returning a new function that wraps the decorated one, executes the decorated function There's a good discussion here. For the main use case, Immediately Invoking a function that expects no parameters, you can just use a simple lambda as decorator or use the existing operator.call:
@lambda f: f()
def func():
print("hey")
hey
@operator.call
def func():
print("hey")
hey
To also support functions that expects parameters we could use a decorator like this:
invoke = lambda *a, **k: lambda _:_(*a, **k)
@invoke(1, 2, 3) # works fine :)
def func(a, b, c):
print(a + b + c)
6
@invoke()
def func():
print("hey")
hey
This is a trick that I don't particularly like and that probably I'll never use, but I've added it here for the sake of knowledge.
No comments:
Post a Comment