Python:设置属性是一个 lambda,只是 returns 一个字典
Python: Setting attribute that is a lambda that just returns a dictionary
在了解装饰器和装饰器工厂的过程中,我检查了 @functools.lru_cache
的源代码,因为它允许使用一个实现来实现这两种用法。我发现了一些让我感兴趣的东西。在下面的语句中 wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
从这个 piece of code from the CPython implementation 中提取:
def lru_cache(maxsize=128, typed=False):
"""<docstring ommited for brevity>"""
if isinstance(maxsize, int):
# Negative maxsize is treated as 0
if maxsize < 0:
maxsize = 0
elif callable(maxsize) and isinstance(typed, bool):
# The user_function was passed in directly via the maxsize argument
user_function, maxsize = maxsize, 128
wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
return update_wrapper(wrapper, user_function)
elif maxsize is not None:
raise TypeError(
'Expected first argument to be an integer, a callable, or None')
def decorating_function(user_function):
wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
return update_wrapper(wrapper, user_function)
return decorating_function
创建仅 returns 字典而不是直接将字典设置为属性的 lambda 的目的是什么?
After thinking a bit on the subject I came to this conclusion. But if there's another reason or you have a more complete explanation, please post an answer so I can accept it :)
字典是 Python 中的可变对象。这意味着任何拥有字典引用的人都可以更改它。所以我认为这里使用 lambda 是使它成为 read-only 属性的一个技巧。看看下面的例子:
def f():
pass
f.a = lambda: {"a": 1}
ref = f.a()
ref
输出:
{'a': 1}
如果您更改返回的字典,则不会影响以下对 lambda 的调用,因为每次调用都会创建一个新字典:
ref["b"] = 2
f.a()
输出:
{'a': 1}
正如您在示例中看到的,返回的字典显然仍然是可变的,但更改它对 lambda 本身的返回值没有影响。
在添加这一行的commit中,我还发现了以下支持我理论的注释:
The wrapped function is instrumented with a :func:cache_parameters
function that returns a new :class:dict
showing the values for maxsize
and typed. This is for information purposes only. Mutating the values
has no effect.
在了解装饰器和装饰器工厂的过程中,我检查了 @functools.lru_cache
的源代码,因为它允许使用一个实现来实现这两种用法。我发现了一些让我感兴趣的东西。在下面的语句中 wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
从这个 piece of code from the CPython implementation 中提取:
def lru_cache(maxsize=128, typed=False):
"""<docstring ommited for brevity>"""
if isinstance(maxsize, int):
# Negative maxsize is treated as 0
if maxsize < 0:
maxsize = 0
elif callable(maxsize) and isinstance(typed, bool):
# The user_function was passed in directly via the maxsize argument
user_function, maxsize = maxsize, 128
wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
return update_wrapper(wrapper, user_function)
elif maxsize is not None:
raise TypeError(
'Expected first argument to be an integer, a callable, or None')
def decorating_function(user_function):
wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
return update_wrapper(wrapper, user_function)
return decorating_function
创建仅 returns 字典而不是直接将字典设置为属性的 lambda 的目的是什么?
After thinking a bit on the subject I came to this conclusion. But if there's another reason or you have a more complete explanation, please post an answer so I can accept it :)
字典是 Python 中的可变对象。这意味着任何拥有字典引用的人都可以更改它。所以我认为这里使用 lambda 是使它成为 read-only 属性的一个技巧。看看下面的例子:
def f():
pass
f.a = lambda: {"a": 1}
ref = f.a()
ref
输出:
{'a': 1}
如果您更改返回的字典,则不会影响以下对 lambda 的调用,因为每次调用都会创建一个新字典:
ref["b"] = 2
f.a()
输出:
{'a': 1}
正如您在示例中看到的,返回的字典显然仍然是可变的,但更改它对 lambda 本身的返回值没有影响。
在添加这一行的commit中,我还发现了以下支持我理论的注释:
The wrapped function is instrumented with a :func:
cache_parameters
function that returns a new :class:dict
showing the values for maxsize and typed. This is for information purposes only. Mutating the values has no effect.