Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decorating a property: right order

Tags:

python

Is there a preferred way of decorating a class property? As I see it you could either decorate the property itself with another property or you could decorate the underlying method and then apply @property on that.
Are there any considerations to make for either approach?

def decorate_property(prop):
    @property
    def inner(instance):
        return prop.__get__(instance) + 1
    return inner

def decorate_func(func):
    def inner(instance):
        return func(instance) +1
    return inner

class A:

    x = 1

    @decorate_property
    @property
    def f(self):
        return self.x

    @property
    @decorate_func
    def g(self):
        return self.x

a = A()
print(a.f) # 2
print(a.g) # 2
like image 517
CoffeeBasedLifeform Avatar asked Apr 25 '19 11:04

CoffeeBasedLifeform


People also ask

Which part of the house should you decorate first?

You should start decorating your living room first. The living room is the room families spend the most time in together, so it's considered a more high-traffic area in your home.

What do you choose first when decorating?

Of course – it's a big task and can seem daunting – so the first thing you do is pick your colour scheme. Usually this comes from looking at a paint chart, or even picking a few samples up from the local DIY shop and painting patches on your walls to see what looks right.


1 Answers

Properties are objects (descriptors) that wrap functions. Which one to decorate depends on which one you intend to change.

  1. If you want to change what the property does, decorate the initial function.

    @property
    @plus_one  # add one to the result of the function
    def a(self):
        return self._a
    

    This also applies to changing the setter and deleter.

    @property
    @plus_one  # add one to the result of the function
    def a(self):
        return self._a
    
    @a.setter
    @minus_one  # remove one from the input of the function
    def a(self, value):
        self._a = value
    
  2. If you want to change what the property is, decorate the resulting descriptor.

    @random_repr  # add a new repr to the descriptor
    @property
    def a(self):
        return 1
    

    Note that defining setter and deleter creates a new descriptor. You need to decorate the last descriptor created.

    @property
    def a(self):
        return self._a
    
    @random_repr  # add a new repr to the final descriptor
    @a.setter
    def a(self, value):
        self._a = value
    

For the most part, a property is used to get a certain behaviour expressed by a function (case 1). The data descriptor (case 2) is an implementation detail that most people are not familiar with. In case of doubt, decorate the function - this case is the more generic and easier to understand.

like image 84
MisterMiyagi Avatar answered Sep 28 '22 18:09

MisterMiyagi