Appengine NDB事务类classmethod Decorator Order

Fox*_*Lad 2 python google-app-engine

我需要以事务方式更新NDB模型的某些属性,并且使更新函数成为类方法似乎是明智的:

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
Run Code Online (Sandbox Code Playgroud)

因此使用:

# Add 25 to cost
thing=Thing.add_cost(thing.key.id(), 25)
Run Code Online (Sandbox Code Playgroud)

装饰者出现的顺序是否重要?

AKS*_*AKS 5

是的,装饰者的顺序很重要.从PEP 318 - 函数和方法的装饰器:

申请顺序[16](从下到上)的基本原理是它与功能应用的通常顺序相匹配.在数学中,函数的组合(g o f)(x)转化为g(f(x)).在Python中,@g @f def foo()转换为foo=g(f(foo).

在您的情况下,它将转换为:

classmethod(ndb.transactional(Thing.add_cost(...)))
Run Code Online (Sandbox Code Playgroud)

装饰器会包装它正在装饰的功能.在这里,你的add_cost函数被包装,ndb.transactional因此函数中的所有东西都发生在事务的上下文中,然后由classmethod它返回的方法返回一个描述符对象.

因此,当您在类中应用多个装饰器时,装饰器(例如classmethod或者staticmethod应该是顶级装饰器).如果您更改顺序TypeError: unbound method ....,如果其他装饰器不接受描述符,您将收到一种错误.

您还可以参考以下帖子了解更多详情:

为什么@decorator不能装饰静态方法或类方法?