gpt4 book ai didi

Python装饰器和类继承

转载 作者:太空狗 更新时间:2023-10-29 20:27:52 26 4
gpt4 key购买 nike

我正在尝试使用装饰器来管理用户在网络应用程序(在 Google App Engine 上运行)中访问或不访问资源的方式。请注意,我不允许用户使用他们的 Google 帐户登录,因此无法在 app.yaml 中设置对特定路由的特定访问权限。

我使用了以下资源:
- Bruce Eckel's guide to decorators
- SO : get-class-in-python-decorator2
- SO : python-decorators-and-inheritance
- SO : get-class-in-python-decorator

不过我还是有点迷糊...

这是我的代码!在下面的示例中,current_user 是属于 RequestHandler 类的 @property 方法。它返回一个存储在数据存储中的 User(db.model) 对象,具有 IntProperty() 级别。

class FoobarController(RequestHandler):

# Access decorator
def requiredLevel(required_level):
def wrap(func):
def f(self, *args):
if self.current_user.level >= required_level:
func(self, *args)
else:
raise Exception('Insufficient level to access this resource')
return f
return wrap

@requiredLevel(100)
def get(self, someparameters):
#do stuff here...

@requiredLevel(200)
def post(self):
#do something else here...

但是,我的应用程序对不同类型的资源使用不同的 Controller 。为了在所有子类中使用 @requiredLevel 装饰器,我需要将它移动到父类 (RequestHandler) 中:

class RequestHandler(webapp.RequestHandler):

#Access decorator
def requiredLevel(required_level):
#See code above

我的想法是使用以下代码访问所有 Controller 子类中的装饰器:

class FoobarController(RequestHandler):

@RequestHandler.requiredLevel(100)
def get(self):
#do stuff here...

我认为我对装饰器和类继承的了解已经达到了极限:)。有什么想法吗?

最佳答案

您的原始代码经过两处小调整后应该也能正常工作。对于这样一个简单的装饰器,基于类的方法似乎相当重量级:

class RequestHandler(webapp.RequestHandler):

# The decorator is now a class method.
@classmethod # Note the 'klass' argument, similar to 'self' on an instance method
def requiredLevel(klass, required_level):
def wrap(func):
def f(self, *args):
if self.current_user.level >= required_level:
func(self, *args)
else:
raise Exception('Insufficient level to access this resource')
return f
return wrap


class FoobarController(RequestHandler):
@RequestHandler.requiredLevel(100)
def get(self, someparameters):
#do stuff here...

@RequestHandler.requiredLevel(200)
def post(self):
#do something else here...

或者,您可以使用 @staticmethod 代替:

class RequestHandler(webapp.RequestHandler):

# The decorator is now a static method.
@staticmethod # No default argument required...
def requiredLevel(required_level):

原始代码不起作用的原因是 requiredLevel 被假定为实例方法,它在类声明时(当您装饰其他方法时)不可用,也不会从类对象中可用(将装饰器放在 RequestHandler 基类上是一个好主意,并且生成的装饰器调用很好地 self 记录)。

您可能有兴趣阅读有关 @classmethod 的文档和 @staticmethod .

此外,我喜欢在我的装饰器中放入一些样板:

    @staticmethod
def requiredLevel(required_level):
def wrap(func):
def f(self, *args):
if self.current_user.level >= required_level:
func(self, *args)
else:
raise Exception('Insufficient level to access this resource')
# This will maintain the function name and documentation of the wrapped function.
# Very helpful when debugging or checking the docs from the python shell:
wrap.__doc__ = f.__doc__
wrap.__name__ = f.__name__
return f
return wrap

关于Python装饰器和类继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3378949/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com