클래스 메소드에서 클래스 필드를 데코레이터에게 인수로 전달하는 방법은 무엇입니까? 내가하고 싶은 것은 다음과 같습니다.
class Client(object):
def __init__(self, url):
self.url = url
@check_authorization("some_attr", self.url)
def get(self):
do_work()
self.url
데코레이터 에게 전달 하기 위해 자아가 존재하지 않는다고 불평합니다 . 이 주위에 방법이 있습니까?
답변
예. 클래스 정의시 인스턴스 속성을 전달하는 대신 런타임시 확인하십시오.
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
답변
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 : 확인
답변
더 간결한 예는 다음과 같습니다.
#/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!
답변
또 다른 옵션은 구문 설탕을 버리고 __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!
답변
당신은 할 수 없습니다. 더 없어 self
더 인스턴스가 존재하지 않기 때문에, 클래스 본문에. str
예를 들어 인스턴스에서 조회하기 위해 속성 이름을 포함하는 전달해야합니다.이 함수는 반환 된 함수가 수행 할 수 있거나 다른 방법을 완전히 사용할 수 있습니다.