The __set_name__ method for descriptors

Descriptors generally have to interact with attributes of the managed object, and this is done by inspecting __dict__ on that object (or calling getattr/setattr, but the problem is the same), and finding the key under the specific name.

For this reason, the descriptor will have to know the name of the key to look for, which is related to the name of the attribute is managing.

On previous versions of Python this had to be done explicitly. If we wanted to work around it, there were some more advanced ways to do so. Luckily, after PEP-487 (added in Python 3.6), there are some enhancements regarding class creation, which also affects descriptors.

Read more...

Descriptors & Decorators

Descriptors are an amazing tool to have in our toolbox, as they come in handy in many opportunities.

Probably the best thing about descriptors, is that they can improve other solutions. Let's see how we can write better decorators, by using descriptors.

Decorate a class method

Imagine we have a very simple decorator, that does nothing but returning a text, with what the original function returns:

class decorator:
    def __init__(self, func):
        self.func = func
        wraps(func)(self)

    def __call__(self, *args, **kwargs):
        result = self.func(*args, **kwargs)
        return f"decorated {result}"

class Object:
    @decorator
    @classmethod
    def class_method(cls):
        return 'class method'

If we apply the decorator to a simple function, it'll work, as expected. However, when it's applied to a class method, we can see an error:

Read more...

__wrapped__ in Python decorators

This is another of the new interesting things that Python 3 has. Time ago, it was somehow tricky to work with decorated functions, because the decorator replaced the original object, and its behaviour became hard to reach.

So, for example, we all know that the following sentence:

@decorator
def function():
    pass

It’s actually syntax sugar for:

def function():
    pass

function = decorator(function)

So, if for some reason, we need to work both with the original and decorated functions, we required tricks such as different names, something like:

Read more...