问题:具有自变量的类方法修饰器?
如何将类字段作为参数传递给类方法的装饰器?我想做的是这样的:
class Client(object):
def __init__(self, url):
self.url = url
@check_authorization("some_attr", self.url)
def get(self):
do_work()
它抱怨自己不存在传递self.url
给装饰器。有没有解决的办法?
回答 0
是。与其在类定义时传递实例属性,不如在运行时检查它:
def check_authorization(f):
def wrapper(*args):
print args[0].url
return f(*args)
return wrapper
class Client(object):
def __init__(self, url):
self.url = url
@check_authorization
def get(self):
print 'get'
>>> Client('http://www.google.com').get()
http://www.google.com
get
装饰器截取方法参数;第一个参数是实例,因此它从中读取属性。您可以将属性名称作为字符串传递给装饰器,并getattr
在不想对属性名称进行硬编码时使用:
def check_authorization(attribute):
def _check_authorization(f):
def wrapper(self, *args):
print getattr(self, attribute)
return f(self, *args)
return wrapper
return _check_authorization
回答 1
from re import search
from functools import wraps
def is_match(_lambda, pattern):
def wrapper(f):
@wraps(f)
def wrapped(self, *f_args, **f_kwargs):
if callable(_lambda) and search(pattern, (_lambda(self) or '')):
f(self, *f_args, **f_kwargs)
return wrapped
return wrapper
class MyTest(object):
def __init__(self):
self.name = 'foo'
self.surname = 'bar'
@is_match(lambda x: x.name, 'foo')
@is_match(lambda x: x.surname, 'foo')
def my_rule(self):
print 'my_rule : ok'
@is_match(lambda x: x.name, 'foo')
@is_match(lambda x: x.surname, 'bar')
def my_rule2(self):
print 'my_rule2 : ok'
test = MyTest()
test.my_rule()
test.my_rule2()
输出:my_rule2:好的
回答 2
更为简洁的示例如下:
#/usr/bin/env python3
from functools import wraps
def wrapper(method):
@wraps(method)
def _impl(self, *method_args, **method_kwargs):
method_output = method(self, *method_args, **method_kwargs)
return method_output + "!"
return _impl
class Foo:
@wrapper
def bar(self, word):
return word
f = Foo()
result = f.bar("kitty")
print(result)
将打印:
kitty!
回答 3
另一个选择是放弃语法糖,并在__init__
该类中进行装饰。
def countdown(number):
def countdown_decorator(func):
def func_wrapper():
for index in reversed(range(1, number+1)):
print("{}".format(index))
func()
return func_wrapper
return countdown_decorator
class MySuperClass():
def __init__(self, number):
self.number = number
self.do_thing = countdown(number)(self.do_thing)
def do_thing(self):
print('im doing stuff!')
myclass = MySuperClass(3)
myclass.do_thing()
将打印
3
2
1
im doing stuff!
回答 4
你不能 有没有self
在类体内,因为没有实例存在。您需要传递它,例如,一个str
包含要在实例上查找的属性名称,然后返回的函数可以执行此操作,或者完全使用其他方法。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。