为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕村225694 2021-04-01 22:19:05
我有一个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)。
查看完整描述

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>)


查看完整回答
反对 回复 2021-04-06
?
繁星淼淼

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。


查看完整回答
反对 回复 2021-04-06
?
喵喵时光机

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


查看完整回答
反对 回复 2021-04-06
  • 3 回答
  • 0 关注
  • 209 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号