python: 属性字段是否自动缓存?
我的问题是,下面这两段代码在解释器运行时是否是一样的:
class A(object):
def __init__(self):
self.__x = None
@property
def x(self):
if not self.__x:
self.__x = ... #some complicated action
return self.__x
还有更简单的:
class A(object):
@property
def x(self):
return ... #some complicated action
也就是说,解释器是否足够聪明,可以记住属性 x
的值?
我的假设是 x
的值不会改变 - 找到它是很“麻烦”的,但一旦找到一次,就没有理由再去找第二次。
8 个回答
19
不,你需要添加一个叫做 memoize 的装饰器:
class memoized(object):
"""Decorator that caches a function's return value each time it is called.
If called later with the same arguments, the cached value is returned, and
not re-evaluated.
"""
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
try:
return self.cache[args]
except KeyError:
value = self.func(*args)
self.cache[args] = value
return value
except TypeError:
# uncachable -- for instance, passing a list as an argument.
# Better to not cache than to blow up entirely.
return self.func(*args)
def __repr__(self):
"""Return the function's docstring."""
return self.func.__doc__
def __get__(self, obj, objtype):
"""Support instance methods."""
return functools.partial(self.__call__, obj)
@memoized
def fibonacci(n):
"Return the nth fibonacci number."
if n in (0, 1):
return n
return fibonacci(n-1) + fibonacci(n-2)
print fibonacci(12)
24
如果你在2020年看到这个内容,想告诉你,这个功能现在在Python 3.8的标准库中可以通过functools
模块使用了。
https://docs.python.org/dev/library/functools.html#functools.cached_property
需要注意的是,定义了自己__dict__
(或者根本没有定义)或者使用__slots__
的类,可能不会按预期工作。比如,NamedTuple
和元类(metaclasses)就是这样的例子。
36
不,获取器(getter)每次你访问这个属性时都会被调用。