Pythonic方式在变量第一次调用时执行工作

8 投票
5 回答
1267 浏览
提问于 2025-04-15 15:14

我的Python类里有一些变量,第一次调用的时候需要进行计算。之后再调用的时候就应该直接返回之前计算好的值。

我不想浪费时间去计算这些值,除非用户真的需要它们。

那么,有没有一种简单、优雅的Python方法来实现这个需求呢?

我最开始的想法是用property()来在第一次调用时执行一个函数,然后再覆盖这个变量:

class myclass(object):
    def get_age(self):
        self.age = 21 # raise an AttributeError here
        return self.age

    age = property(get_age)

谢谢

5 个回答

5

这里有一个来自《Python Cookbook》的装饰器,专门用来解决这个问题:

class CachedAttribute(object):
    ''' Computes attribute value and caches it in the instance. '''
    def __init__(self, method, name=None):
        # record the unbound-method and the name
        self.method = method
        self.name = name or method.__name__
    def __get__(self, inst, cls):
        if inst is None:
            # instance attribute accessed on class, return self
            return self
        # compute, cache and return the instance's attribute value
        result = self.method(inst)
        setattr(inst, self.name, result)
        return result
6

你看到的property是不能被覆盖的。你需要用一种稍微不同的方法,比如:

class myclass(object):

    @property
    def age(self):
      if not hasattr(self, '_age'):
        self._age = self._big_long_computation()
      return self._age

还有其他的方法,比如__getattr__或者自定义描述符类,但这个方法更简单!-)

15
class myclass(object):
    def __init__(self):
        self.__age=None
    @property
    def age(self):
        if self.__age is None:
            self.__age=21  #This can be a long computation
        return self.__age

Alex提到你可以使用 __getattr__,这是它的工作原理

class myclass(object):
    def __getattr__(self, attr):
        if attr=="age":
            self.age=21   #This can be a long computation
        return super(myclass, self).__getattribute__(attr)

__getattr__() 会在你尝试访问一个对象上不存在的属性时被调用,比如说第一次你试图访问 age 的时候。之后每次访问 age 时,它已经存在了,所以就不会再调用 __getattr__ 了。

撰写回答