从装饰器访问函数参数
我有一个请求处理器和一个装饰器,我想在装饰器里面使用self对象。
class MyHandler(webapp.RequestHandler):
@myDecorator
def get(self):
#code
更新:请注意第一个和第二个self的区别
class myDecorator(object):
def __init__(self, f):
self.f = f
def __call__(self):
#work with self
MyHandler
>get
(函数)>self
(参数)myDecorator
>__call__
(函数)>self
(参数)
上面提到的self参数是不同的。我的目的是想在__call__
函数里面访问第一个self,或者找到类似的方法。
你好,我能在装饰器里面从get函数访问MyHandler的self参数吗?
更新2:我想实现一个装饰器,用于在谷歌应用引擎中处理自定义登录:
我有一个类(requestHandler):
class SomeHandler(webapp.RequestHandler):
@only_registered_users
def get(self):
#do stuff here
我想装饰get函数,以检查用户是否已登录:
from util.sessions import Session
import logging
class only_registered_users(object):
def __init__(self, f):
self.f = f
def __call__(self):
def decorated_get(self):
logging.debug("request object:", self.request)
session = Session()
if hasattr(session, 'user_key'):
return self.f(self)
else:
self.request.redirect("/login")
return decorated_get
我知道如果用户已登录,session对象中会有一个属性'user_key'。
这是我在这个特定案例中最关心的主要目标。
如果我做错了什么,请告诉我你的建议/意见!
谢谢!
5 个回答
1
试试这个方法:一个Python实例方法的装饰器能访问类吗?
虽然这个问题不完全一样,但你可以用类似的方法来创建对self的引用,或者创建一个包含某个类对象的字典,这样你就可以在你的装饰器中使用这些引用。
2
def p_decorate(func):
def func_wrapper(name):
return "<p>{0}</p>".format(func(name))
return func_wrapper
@p_decorate
def get_text(name):
return "lorem ipsum, {0} dolor sit amet".format(name)
print get_text("John")
# Outputs <p>lorem ipsum, John dolor sit amet</p>
11
我不太清楚你具体想要什么,但如果你只是想使用被装饰函数的参数,那这正是基本装饰器的作用。所以,如果你想从装饰器中访问,比如说,self.request
,你可以这样做:
def log_request(fn):
def decorated_get(self):
logging.debug("request object:", self.request)
return fn(self)
return decorated_get
class MyHandler(webapp. RequestHandler):
@log_request
def get(self):
self.response.out.write('hello world')
如果你想访问被装饰函数所附加的类,那就有点复杂了,你需要借助一下 inspect 模块。
import inspect
def class_printer(fn):
cls = inspect.getouterframes(inspect.currentframe())[1][3]
def decorated_fn(self, msg):
fn(self,cls+" says: "+msg)
return decorated_fn
class MyClass():
@class_printer
def say(self, msg):
print msg
在上面的例子中,我们从当前执行的帧中获取类的名称(在装饰器执行时),然后把这个名称存储在被装饰的函数里。这里我们只是把类名加到 msg
变量前面,然后再传给原来的 say
函数,但一旦你有了类名,你可以发挥想象力,做任何你想做的事情。
>>> MyClass().say('hello')
MyClass says: hello