Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic way, syntax-sugar or operator for applying a function to self?

Tags:

python

Imagine having a long-named or nested collection/dictionary of function objects, if I want to apply decorator to some of them based on certain conditions, I'll have to:

long_long_name[some_key][some_other, key] = my_decorator(long_long_name[some_key][some_other, key])

Is there a pythonic way / syntax-sugar to do it ? like plus-equal for addition to self ?

a = a + b # can be written as
a += b

a = b(a)
a ◯= b # something like this ?
like image 789
Max Chen Avatar asked Oct 15 '25 15:10

Max Chen


1 Answers

I don't think it would be a good idea, but something similar to what you want is possible.

If you can decorate all your callables, you could add such an operation, for example with the @= operator, which is usually not defined for functions:

The first step would be to declare the decorator that you have to apply to all of your callables:

class decoratable:
    def __init__(self, fn):
        self.fn = fn
    def __matmul__(self, other):
        return decoratable(other(self.fn))
    def __call__(self, *args, **kwargs):
        return self.fn(*args, **kwargs)

If you manage to decorate all of your callables with this decorator, then you can use @ to combine them with other decorators:

@decoratable
def add_2(x):
    return x + 2

long_long_name = {"some_key": {("other", "key"): add_2}}

Let's define an example decorator that prints when you call the function:

def printer(fn):
    def wrapper(*args, **kwargs):
        print(f"Calling {fn.__name__}")
        return fn(*args, **kwargs)
    return wrapper

Then, finally, this becomes possible:

>>> long_long_name["some_key"]["other", "key"](3)
5
>>> long_long_name["some_key"]["other", "key"] @= printer
>>> long_long_name["some_key"]["other", "key"](3)
Calling add_2
5
like image 117
L3viathan Avatar answered Oct 19 '25 14:10

L3viathan