Class 类 中方法的装饰器
Class decorators for methods in classes
class class 中方法的装饰器如何工作?这是我通过一些实验所做的示例:
from functools import wraps
class PrintLog(object):
def __call__(self, func):
@wraps(func)
def wrapped(*args):
print('I am a log')
return func(*args)
return wrapped
class foo(object):
def __init__(self, rs: str) -> None:
self.ter = rs
@PrintLog()
def baz(self) -> None:
print('inside baz')
bar = foo('2')
print('running bar.baz()')
bar.baz()
这非常好用。然而,我的印象是装饰器不需要用 ()
调用,但是当我从 @PrintLog()
中删除括号时,我得到这个错误:
def baz(self) -> None:
TypeError: PrintLog() takes no arguments
我是不是有什么地方missing/do不明白?我也试过用 __init__()
传递一个一次性 arg,它起作用了。
class PrintLog(object):
def __init__(self, useless):
print(useless)
def __call__(self, func):
@wraps(func)
def wrapped(*args):
print('I am a log')
return func(*args)
return wrapped
class foo(object):
def __init__(self, rs: str) -> None:
self.ter = rs
@PrintLog("useless arg that I'm passing to __init__")
def baz(self) -> None:
print('inside baz')
同样,这可行,但我不想将任何参数传递给装饰器。
tl;dr: This question 在 python 3.x.
感谢帮助!
Class 装饰器接受函数作为 __init__
方法中的主题(因此是日志消息),因此您的装饰器代码应如下所示:
class PrintLog(object):
def __init__(self, function):
self.function = function
def __call__(self):
@wraps(self.function)
def wrapped(*args):
print('I am a log')
return self.function(*args)
return wrapped
抱歉,如果这不起作用,我会在我的移动设备上回答。
编辑:
好吧,这可能不是你想要的,但这是实现它的方法:
from functools import update_wrapper, partial, wraps
class PrintLog(object):
def __init__(self, func):
update_wrapper(self, func)
self.func = func
def __get__(self, obj, objtype):
"""Support instance methods."""
return partial(self.__call__, obj)
def __call__(self, obj, *args, **kwargs):
@wraps(self.func)
def wrapped(*args):
print('I am a log')
return self.func(*args)
return wrapped(obj, *args)
class foo(object):
def __init__(self, rs: str) -> None:
self.ter = rs
@PrintLog
def baz(self) -> None:
print('inside baz')
bar = foo('2')
print('running bar.baz()')
bar.baz()
装饰器必须定义 __get__
方法,因为您要将装饰器应用于实例方法。描述符如何具有 foo
实例的上下文?
参考:Decorating Python class methods - how do I pass the instance to the decorator?
你错过了一张大图。
@decorator
def foo(...):
function_definition
与
几乎相同(除了一些内部修改)
temp = foo
foo = decorator(temp)
装饰器是什么并不重要,只要它能像一个函数一样。
你的例子相当于:
baz = PrintLog("useless thing")(<saved defn of baz>)
由于 PrintLog
是 class,PrintLog(...)
创建了 PrintLog
的一个实例。该实例有一个 __call__
方法,因此它可以像一个函数一样工作。
一些装饰器被设计成接受参数。一些装饰器被设计成不接受参数。有些,比如 @lru_cache
,是 Python 魔法的一部分,它查看“参数”是一个函数(因此装饰器被直接使用)还是一个 number/None,以便它returns 一个函数,然后成为装饰器。
class class 中方法的装饰器如何工作?这是我通过一些实验所做的示例:
from functools import wraps
class PrintLog(object):
def __call__(self, func):
@wraps(func)
def wrapped(*args):
print('I am a log')
return func(*args)
return wrapped
class foo(object):
def __init__(self, rs: str) -> None:
self.ter = rs
@PrintLog()
def baz(self) -> None:
print('inside baz')
bar = foo('2')
print('running bar.baz()')
bar.baz()
这非常好用。然而,我的印象是装饰器不需要用 ()
调用,但是当我从 @PrintLog()
中删除括号时,我得到这个错误:
def baz(self) -> None:
TypeError: PrintLog() takes no arguments
我是不是有什么地方missing/do不明白?我也试过用 __init__()
传递一个一次性 arg,它起作用了。
class PrintLog(object):
def __init__(self, useless):
print(useless)
def __call__(self, func):
@wraps(func)
def wrapped(*args):
print('I am a log')
return func(*args)
return wrapped
class foo(object):
def __init__(self, rs: str) -> None:
self.ter = rs
@PrintLog("useless arg that I'm passing to __init__")
def baz(self) -> None:
print('inside baz')
同样,这可行,但我不想将任何参数传递给装饰器。
tl;dr: This question 在 python 3.x.
感谢帮助!
Class 装饰器接受函数作为 __init__
方法中的主题(因此是日志消息),因此您的装饰器代码应如下所示:
class PrintLog(object):
def __init__(self, function):
self.function = function
def __call__(self):
@wraps(self.function)
def wrapped(*args):
print('I am a log')
return self.function(*args)
return wrapped
抱歉,如果这不起作用,我会在我的移动设备上回答。
编辑:
好吧,这可能不是你想要的,但这是实现它的方法:
from functools import update_wrapper, partial, wraps
class PrintLog(object):
def __init__(self, func):
update_wrapper(self, func)
self.func = func
def __get__(self, obj, objtype):
"""Support instance methods."""
return partial(self.__call__, obj)
def __call__(self, obj, *args, **kwargs):
@wraps(self.func)
def wrapped(*args):
print('I am a log')
return self.func(*args)
return wrapped(obj, *args)
class foo(object):
def __init__(self, rs: str) -> None:
self.ter = rs
@PrintLog
def baz(self) -> None:
print('inside baz')
bar = foo('2')
print('running bar.baz()')
bar.baz()
装饰器必须定义 __get__
方法,因为您要将装饰器应用于实例方法。描述符如何具有 foo
实例的上下文?
参考:Decorating Python class methods - how do I pass the instance to the decorator?
你错过了一张大图。
@decorator
def foo(...):
function_definition
与
几乎相同(除了一些内部修改)temp = foo
foo = decorator(temp)
装饰器是什么并不重要,只要它能像一个函数一样。
你的例子相当于:
baz = PrintLog("useless thing")(<saved defn of baz>)
由于 PrintLog
是 class,PrintLog(...)
创建了 PrintLog
的一个实例。该实例有一个 __call__
方法,因此它可以像一个函数一样工作。
一些装饰器被设计成接受参数。一些装饰器被设计成不接受参数。有些,比如 @lru_cache
,是 Python 魔法的一部分,它查看“参数”是一个函数(因此装饰器被直接使用)还是一个 number/None,以便它returns 一个函数,然后成为装饰器。