ovgolovin
ovgolovin

Reputation: 13410

Using descriptor to access variable instead of binding this variable with the target in the instance

I have just been reading momoko docs, and came across the following class:

class BaseHandler(RequestHandler):
    @property
    def db(self):
        return self.application.db

Every time we want to access db attribute of base_handler instance of BaseHandler, the db(self) will be called, returning self.application.db.

What is the advantage of this code over the following?

class BaseHandler(RequestHandler):
    def __init__(self):
        self.db = self.application.db

This will bind instance variable db to self.application.db.

I understand that the former approach will avoid us of having self.db in each instance. On the other hand, self.application.db has extra attribute resolution step (extra .).

Are there any advantages of the former approach that I don't see?

Upvotes: 1

Views: 51

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121654

It makes db read-only. You cannot set base_handler.db, there is no setter associated with the property:

>>> class Foo(object):
...     @property
...     def bar(self): return 'spam'
... 
>>> foo = Foo()
>>> foo.bar
'spam'
>>> foo.bar = 'ham'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

You'd need to add a setter for it to be writable:

class Foo(object):
    _bar = 'spam'

    @property
    def bar(self):
        return self._bar

    @bar.setter
    def bar(self, value):
        self._bar = value

Note the @name_of_property.setter decorator; the property object itself gives you a decorator function to create a new decorator with the setter replaced with the new decorated function. There is a .deleter equivalent as well. See the property function documentation for more detail.

Upvotes: 4

Related Questions