2

I need to update some properties of an NDB model transactionally, and it seems sensible to make the update function a classmethod:

class Thing(ndb.Model): cost=ndb.IntegerProperty() @classmethod @ndb.transactional() def add_cost(cls, thid, amount): thing=cls.get_by_id(thid) thing.cost+=amount return thing 

This is used thus:

# Add 25 to cost thing=Thing.add_cost(thing.key.id(), 25) 

Does it matter which order the decorators appear?

1 Answer 1

5

Yes, the order of decorators does matter. From the PEP 318 -- Decorators for Functions and Methods:

The rationale for the order of application [16] (bottom to top) is that it matches the usual order for function-application. In mathematics, composition of functions (g o f)(x) translates to g(f(x)). In Python, @g @f def foo() translates to foo=g(f(foo).

In your case it would translate to:

classmethod(ndb.transactional(Thing.add_cost(...))) 

A decorator would wrap the function it is decorating. Here, your add_cost function is wrapped by ndb.transactional so everything thing within the function happens in the context of a transaction and then the method returned by that is wrapped by classmethod which returns a descriptor object.

So, when you apply multiple decorators in a class, then decorators such as classmethod or staticmethod should be the top ones. If you change the order you would receive an TypeError: unbound method .... type of error if the other decorator doesn't accept descriptors.

You can also refer to following post for more details:

Why can @decorator not decorate a staticmethod or a classmethod?

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.