简体   繁体   English

在python中获取属性的属性

[英]Get attribute of a property in python

I have a decorator which simply caches return values (called @cached in my example) and I wish to use it in conjunction with @property . 我有一个装饰它只是缓存返回值(称为@cached在我的例子),我想结合使用@property This works just fine normally. 这通常正常工作。 The problem I am facing occurs when I try and use an expire attribute added by @cached . 当我尝试使用@cached添加的expire属性时,会遇到我面临的问题。

def cached(f):
    cache = [None]

    def inner(*args, **kwargs):
        if cache[0]:
            cache[0] = f(*args, **kwargs)
        return cache[0]

    def expire():
        cache[0] = None

    inner.expire = expire
    return inner

class Example(object):
    @property
    @cached
    def something_expensive(self):
        print("expensive")
        return "hello"


e = Example()
e.something_expensive
e.something_expensive.expire()

How am I able to get access to the expire function? 我如何能够访问到期功能? added to the function after its replaced by @property . 在将其替换为@property后添加到函数中。 I understand why this doesn't work I am interested in a way of working around that problem. 我了解为什么这不起作用,我对解决该问题感兴趣。

Some restrictions: 一些限制:

  • I cannot change the @cached decorator its in a library I don't control 我无法在我无法控制的库中更改@cached装饰器
  • I would really rather not remove @property because I want to expire in my unit tests and they make my code much nicer to use. 我真的不希望删除@property因为我想在单元测试中过期,它们会使我的代码更易于使用。

One solution that I think is rather bad is (because In reality I have a lot of properties that I want to do this for): 我认为很糟糕的一种解决方案是(因为实际上我有很多属性要为此执行):

class Example(object):
    @cached
    def _something_expensive(self):
        return "hello"

    @property
    def something_expensive(self):
        return self._something_expensive()

You can access it using the class dictionary: 您可以使用类字典访问它:

type(e).__dict__['something_expensive'].fget.expire()

In general e.something_expensive is equivalent to: 通常, e.something_expensive等效于:

type(e).__dict__['something_expensive'].__get__(e, type(e))

For more details read up: Descriptor HowTo Guide 有关更多详细信息,请阅读: 描述符方法指南

Note that inside the expiry function you're not setting cache from the outer function cached function as None , you're simply creating a new local variable. 需要注意的是内expiry的功能你不设置cache从外部函数cached功能None ,你只是创建一个新的局部变量。 You may want to do something like this: 您可能需要执行以下操作:

def expire():
    del cache[:]
    cache.append(None)

In Python 3 it's even easier to update cache using the nonlocal keyword. 在Python 3中,使用nonlocal关键字更新cache更加容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM