Hemanth.HM

A Computer Polyglot, CLI + WEB ♥'r.

Descriptor Decorator in Python

| Comments

Decorators and Descriptor are two independent features of Python programming language, but they gel together very well, below is a descriptor decorator ;)

Say, we have a simple Greet class:

1
2
3
4
class Greet():
    msg = "meow"
    def yo(self):
        return "Yo!"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> Greet()
<__main__.Greet object at 0x10046ea90>

>>> greetThem = Greet()

>>> greetThem.yo
<bound method Greet.yo of <__main__.Greet object at 0x10046eb50>>

>>> greetThem.msg
"meow"

>>> greetThem.yo()
"Yo!"

>>> Greet.msg
"meow"

Nothing special so far, everything is as expected...

Now, let's add some magic, first lets create an Accessor descriptor:

1
2
3
4
5
6
7
8
class Accessor(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, type):
        if obj is None:
            return self
        return self.fget(obj)

Now that we have a descriptor, let's decorate our Greet class with it.

1
2
3
4
5
class Greet():
    msg = "meow"
    @Accessor
    def yo(self):
        return "Yo!"
1
2
3
4
5
6
7
8
9
10
11
12
13
>>> Greet()
<__main__.Greet object at 0x10056eb50>

>>> greetThem = Greet()

>>> greetThem.yo
"Yo!"

>>> greetThem.msg
"meow"

>>> Greet.msg
"meow"

Notice greetThem.yo vs greetThem.yo() :)

So what was the trick behind the magic?:

Dotted access to look up a member will result in:

  • Look up for the member in the instance dictionary.

  • If it's not found, the look up happens in the class dictionary.

  • If found it in the class dictionary and it has a descriptor protocol implemented, instead of just returning it, Python executes it!

Clearly the much more concise term of art should be Desecrator, says coriolinus on reddit.

Comments