当前位置: 首页 > 面试题库 >

在@property之后装饰类方法

百里成仁
2023-03-14
问题内容

我想__init__使用装饰器包装各种对象的每种方法。

class MyObject(object):

    def method(self):
        print "method called on %s" % str(self)

    @property
    def result(self):
        return "Some derived property"

def my_decorator(func):
    def _wrapped(*args, **kwargs):
        print "Calling decorated function %s" % func
        return func(*args, **kwargs)
    return _wrapped


class WrappedObject(object):

    def __init__(self, cls):
        for attr, item in cls.__dict__.items():
            if attr != '__init__' and (callable(item) or isinstance(item, property)):
                setattr(cls, attr, my_decorator(item))
        self._cls = cls

    def __call__(self, *args, **kwargs):
        return self._cls(*args, **kwargs)

inst = WrappedObject(MyObject)()

但是,属性实例结果的包装与此等效:

@my_decorator
@property
def result(self):
    return "Some derived property"

当所需的结果与此等效时:

@property
@my_decorator
def result(self):
    return "Some derived property"

似乎属性对象的属性是只读的,因此在属性将其包装之后,无法修改该函数。我对已经需要的黑客级别不太满意,无论如何我也不希望深入研究该属性对象。

我能看到的唯一其他解决方案是即时生成一个我希望避免的元类。我是否缺少明显的东西?


问题答案:

此示例中还有其他一些问题,但是有个疑问,您要做的就是包装属性时

包装属性时,请包装其__get__方法:

class MyObject(object):

    def method(self):
        print "method called on %s" % str(self)

    @property
    def result(self):
        return "Some derived property"

    def common(self, a=None):
        print self

def my_decorator(func):
    def _wrapped(*args, **kwargs):
        print "Calling decorated function %s" % func
        return func(*args, **kwargs)
    return _wrapped


class WrappedObject(object):

    def __init__(self, cls):
        for attr, item in cls.__dict__.items():
            if attr != '__init__' and callable(item):
                setattr(cls, attr, my_decorator(item))
            elif  isinstance(item, property):
                new_property = property(my_decorator(item.__get__), item.__set__, item.__delattr__)
                setattr(cls, attr, new_property)
        self._cls = cls

    def __call__(self, *args, **kwargs):
        return self._cls(*args, **kwargs)

inst = WrappedObject(MyObject)()

那就是对完成任务的代码的简单修改。但是,为了避免重新编写其属性,我将其更改为包装的类的子类。您可以通过编程简单地创建带有名称的类型,带有基数的元组和以dict为参数的子类,从而以编程方式创建子类。

编辑-将代码更改为子类包装的类

实际上,对给定类进行子类化几乎不需要对给定代码进行任何修改,但是对于type我指出的调用而言。我刚刚在这里进行了测试-
将WrappedObject类更改为:

class WrappedObject(object):

    def __init__(self, cls):
        dct = cls.__dict__.copy()
        for attr, item in dct.items():
            if attr != '__init__' and callable(item):
                dct[attr] =  my_decorator(item)
            elif  isinstance(item, property):
                new_property = property(my_decorator(item.__get__), item.__set__, item.__delattr__)
                dct[attr] = new_property
        self._cls = type("wrapped_" + cls.__name__, (cls,), dct)

    def __call__(self, *args, **kwargs):
        return self._cls(*args, **kwargs)


 类似资料:
  • 问题内容: 我试图在类中的字典上使用Python的装饰器。我的想法是我希望在访问某个值后将其清除(称为“消息”)。但是我还希望另一个值(称为“ last_message”)包含最后设置的消息,并将其保留直到设置了另一个消息。在我看来,此代码将有效: 但是,它似乎没有: 我不确定自己做错了什么?在我看来,这似乎不像我期望的那样起作用,但是也许我在做其他根本上错误的事情? 另外,我知道我可以在类中使用

  • 问题内容: 考虑这个小例子: 哪个打印 为什么参数(应该是Test obj实例)没有作为第一个参数传递给装饰函数? 如果我手动进行操作,例如: 它按预期工作。但是,如果我必须事先知道某个函数是否装饰,它就破坏了装饰器的全部目的。这里的模式是什么,还是我误会了什么? 问题答案: tl; dr 您可以通过将类作为描述符并返回部分应用的函数来解决此问题,该函数从中应用对象作为参数之一,如下所示 实际问题

  • 问题内容: 我想了解内置功能的工作原理。令我感到困惑的是,它还可以用作装饰器,但是仅当用作内置函数时才接受参数,而不能用作装饰器。 这个例子来自文档: 的论点是和文档字符串。 在下面的代码中用作装饰器。它的对象是函数,但是在上面的代码中,参数中没有对象函数的位置。 并且,和装饰器是如何创建的?我很困惑。 问题答案: 该函数返回一个特殊的描述符对象: 正是这种对象有额外的方法: 这些充当装饰过。他们

  • 本文向大家介绍Python @property装饰器原理解析,包括了Python @property装饰器原理解析的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了Python @property装饰器原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.通过@property装饰器,可以直接通过方法名来访问方法,不需要在方法名后

  • 问题内容: 我正在尝试装饰类中的方法,但是python抛出错误。我的课看起来像这样: : Python抛出以下错误 我要去哪里玩? 问题答案: Python自动将类实例作为参考传递。(在所有类方法中都可以看到的参数)。 您可以这样做:

  • 问题内容: 举个例子: 我遇到的问题是,甚至在我调用要装饰的函数之前就调用了。 开始输出: 在这一点上,我什至没有调用过一个装饰过的函数。 我刚刚开始使用装饰器,所以也许我缺少了一些东西。 问题答案: 我相信python装饰器只是语法糖。 和…一样 如您所见,即使没有调用 bar 也将调用 foo 。这就是为什么您看到装饰器函数的输出的原因。对于您将装饰器应用到的每个函数,您的输出应只包含一行。

  • 本文向大家介绍基于Python 装饰器装饰类中的方法实例,包括了基于Python 装饰器装饰类中的方法实例的使用技巧和注意事项,需要的朋友参考一下 title: Python 装饰器装饰类中的方法 comments: true date: 2017-04-17 20:44:31 tags: ['Python', 'Decorate'] category: ['Python'] --- 目前在中文网

  • 问题内容: 我想这就是它们的称呼,但我会举一些例子以防万一。 装饰类: 装饰器功能: 使用一个或另一个只是口味的问题吗?有实际区别吗? 问题答案: 如果您可以编写函数来实现装饰器,则应首选它。但是并非所有装饰器都可以轻松地编写为一个函数-例如,当您要存储一些内部状态时。 我见过人们(包括我自己)经过荒唐的努力,只用函数编写装饰器。我仍然不知道为什么,一个班级的开销通常可以忽略不计。