Appengine NDB交易类方法装饰器订单 [英] Appengine NDB transactional classmethod Decorator Order
问题描述
我需要事务性地更新NDB模型的某些属性,并且将更新函数设置为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
$
#将25添加到成本
thing = Thing.add_cost(b $ b thing.key.id(),25)
装饰器出现的顺序是否重要? p>
是的,装饰器的顺序很重要。从 PEP 318 - 功能和方法装饰器 :
申请顺序[16] (从下到上)是它与函数申请的通常顺序相匹配。在数学中,函数的构成转化为
g(f(x))
。在Python中,@g @f def foo()
转换为foo = g(f(foo)
p>
在您的情况下,它会转化为:
classmethod(ndb.transactional(Thing.add_cost(...)))
一个装饰器在这里,你的 add_cost
函数被 ndb.transactional
包装,函数发生在事务的上下文中,然后由它返回的方法被 classmethod
包装,它返回一个描述符对象。
你在一个类中应用多个装饰器,然后装饰器如 classmethod
或 staticmethod
应该是最顶层的。您将收到 TypeError:unbound method ....
的错误类型其他装饰者不接受描述符。
您也可以参考以下帖子了解更多详情:
< a @ href =https://stackoverflow.com/a/6208458/2549021>为什么@decorator不能装饰静态方法或classmethod?
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?
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 tog(f(x))
. In Python,@g @f def foo()
translates tofoo=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?
这篇关于Appengine NDB交易类方法装饰器订单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!