猿问

在python中发现修饰的类实例方法

我有一个python类,例如:


class Book(models.Model):

    enabled     = models.BooleanField(default=False)

    full_title  = models.CharField(max_length=256)

    alias       = models.CharField(max_length=64)

    author      = models.CharField(max_length=64)

    status      = models.CharField(max_length=64)

    @serializable

    def pretty_status(self):

        return [b for a, b in BOOK_STATUS_CHOICES if a == self.status][0]

方法pretty_status用@serializable装饰。


在具有特定修饰的类中发现方法的最简单,最有效的方法是什么?(在上面的示例中为:pretty_status)。


慕村225694
浏览 210回答 3
3回答

小唯快跑啊

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

繁星淼淼

一般来说,您不能。装饰器只是用于应用可调用对象的语法糖。在您的情况下,装饰器语法会转换为:def pretty_status(self):&nbsp; &nbsp; 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):&nbsp; &nbsp; def wrapper(*args, **kw):&nbsp; &nbsp; &nbsp; &nbsp; # ...&nbsp; &nbsp; wrapper.__wrapped__ = func&nbsp; &nbsp; return wrapper您可以向该包装函数添加任意数量的属性,包括您自己选择的自定义属性:def serializable(func):&nbsp; &nbsp; def wrapper(*args, **kw):&nbsp; &nbsp; &nbsp; &nbsp; # ...&nbsp; &nbsp; wrapper._serializable = True&nbsp; &nbsp; return wrapper然后测试该属性:if getattr(method, '_serializable', False):&nbsp; &nbsp; print "Method decorated with the @serializable decorator"您可以做的最后一件事是测试该包装器函数;它会有一个.__name__可以测试的属性。该名称可能不是唯一的,但这只是一个开始。在上面的示例装饰器中,包装函数称为wrapper,因此pretty_status.__name__ == 'wrapper'将为True。

喵喵时光机

您不能直接发现它们,但是可以用一些标志标记修饰的方法。import functoolsdef serializable(func):&nbsp; &nbsp; functools.wraps(func)&nbsp; &nbsp; def wrapper(*args, **kw):&nbsp; &nbsp; &nbsp; &nbsp; # ...&nbsp; &nbsp; wrapper._serializable = True&nbsp; &nbsp; return wrapper然后,您可以使元类例如分析_serializable属性的存在或不存在。或者您可以在装饰器中收集所有包装的方法import functoolsDECORATED = {}def serializable(func):&nbsp; &nbsp; functools.wraps(func)&nbsp; &nbsp; def wrapper(*args, **kw):&nbsp; &nbsp; &nbsp; &nbsp; # ...&nbsp; &nbsp; DECORATED[func.__name__] = wrapper&nbsp; &nbsp; return wrapper
随时随地看视频慕课网APP

相关分类

Python
我要回答