3 回答

TA贡献1863条经验 获得超2个赞
如果您无法控制装饰器的功能,则通常无法确定装饰器的方法。
但是,由于可以修改serializable,因此可以将属性添加到包装的函数中,以供以后标识序列化方法时使用:
import inspect
def serializable(func):
def wrapper(self):
pass
wrapper.serialized = True
return wrapper
class Book:
@serializable
def pretty_status(self):
pass
def foo(self):
pass
for name, member in inspect.getmembers(Book, inspect.ismethod):
if getattr(member, 'serialized', False):
print(name, member)
产量
('pretty_status', <unbound method Book.wrapper>)

TA贡献1775条经验 获得超11个赞
一般来说,您不能。装饰器只是用于应用可调用对象的语法糖。在您的情况下,装饰器语法会转换为:
def pretty_status(self):
return [b for a, b in BOOK_STATUS_CHOICES if a == self.status][0]
pretty_status = serializable(pretty_status)
也就是说,pretty_status被任何serializable()回报所取代。它返回的可能是任何东西。
现在,如果serializable返回值本身已经被修饰,functools.wraps()并且您正在使用Python 3.2或更高版本,那么您可以看到.__wrapped__new.pretty_status方法上是否有一个属性;它是对原始包装函数的引用。
在早期版本的Python上,您也可以轻松地自己执行此操作:
def serializable(func):
def wrapper(*args, **kw):
# ...
wrapper.__wrapped__ = func
return wrapper
您可以向该包装函数添加任意数量的属性,包括您自己选择的自定义属性:
def serializable(func):
def wrapper(*args, **kw):
# ...
wrapper._serializable = True
return wrapper
然后测试该属性:
if getattr(method, '_serializable', False):
print "Method decorated with the @serializable decorator"
您可以做的最后一件事是测试该包装器函数;它会有一个.__name__可以测试的属性。该名称可能不是唯一的,但这只是一个开始。
在上面的示例装饰器中,包装函数称为wrapper,因此pretty_status.__name__ == 'wrapper'将为True。

TA贡献1846条经验 获得超7个赞
您不能直接发现它们,但是可以用一些标志标记修饰的方法。
import functools
def serializable(func):
functools.wraps(func)
def wrapper(*args, **kw):
# ...
wrapper._serializable = True
return wrapper
然后,您可以使元类例如分析_serializable属性的存在或不存在。
或者您可以在装饰器中收集所有包装的方法
import functools
DECORATED = {}
def serializable(func):
functools.wraps(func)
def wrapper(*args, **kw):
# ...
DECORATED[func.__name__] = wrapper
return wrapper
添加回答
举报