Fifth Example. Creating partial functions.

Sometimes you need to change a function to accept less arguments: the original function can be several customizable, but you want to offer it with quite less parameters or to use it with quite less parameters.

The former should not be solved using AOP, because you have detected the necesity statically, but the latter can be an issue to be tackled. In fact, functools define a partial function to solve this situations.

During this example, we will explain how to modify the original functions to have partial versions using the before PointCut.

REMEMBER: Trying to be as clean as possible, we strongly recomend you to create a new aspects.py file and add the Aspects to this file.

Library import

First of all, we need to import to the Aspects file the libraries and modules that will be used. In this case, random.

from aspectify.aop import Aspect
from random import Random

Additionally, we need to define the get_classes method.

def get_classes():
    return [element for element in list(globals().items())]

advice definition

In this example, we will define an Aspect called partial_aspect, and we will modify it behaviour during the example.

partial_aspect = Aspect()

As previously seen, we can add a before advice, just using the set_before method.

partial_aspect.set_before(lambda *a, **k: [10, *a])

In this case, we change the input paramets: we fix the first argument to be 10 and let the others like in the original call.

It is important to note that we have added a new fixed argument to the call, so now we can call the function with only one parameter. In fact, if we call it with two of them, it will raise an error. It can be also solved by creating the new arguments with *a[:X], were X will be the number of dynamically set parameters.

Finally, we catch the randint method from random.

partial_aspect.create_pointcut(get_classes(), "random.Random.randint")
Captured method: random.Random.randint

Results

Now, we can call the randint method, which will return a random number in [a,b]

r = Random()
r.randint(20)
WARNING:root:Args changed from [<random.Random object>, 20] to [<random.Random object>, 10, 20]
13

Conclusion

During this example we have explained how to use a before PointCut to build a partial function: a simplified function using another one. Those partial functions are not the same that partials from functools, since those functions override the original behaviour of the method: we will use the same name, but the change is not reversible.