python nonlocal 什么意思_python nonlocal的理解使用

python nonlocal 什么意思_python nonlocal的理解使用nonlocal 可以将一个变量声明为非本地变量 在 python 的 lru cache 看到了使用 defdecorator func a 1defwrapper args kwargs nonlocalaa 1returnfunc returnwrappe 实例中 当 a 变量是不可变类型时 因为包装函数引用了 a 装饰器执行结束 在包装函数里改变 a 的值 需要

nonlocal 可以将一个变量声明为非本地变量, 在python的lru_cache看到了使用

def decorator(func):

a = 1

def wrapper(*args, kwargs):

nonlocal a

a += 1

return func()

return wrapper

实例中, 当a变量是不可变类型时, 因为包装函数引用了a, 装饰器执行结束, 在包装函数里改变a的值, 需要用nonlocal声明a变量. (a是自由变量了)

当a是可变类型时, 可以不用声明nonlocal a

自己再本地试一遍能理解的更加深入

lru_cache源码中的使用, 用来记录hit和miss

只贴出包装函数的部分

f _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo):

# Constants shared by all lru cache instances:

sentinel = object() # unique object used to signal cache misses

make_key = _make_key # build a key from the function arguments

PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields

cache = {}

hits = misses = 0

full = False

cache_get = cache.get

cache_len = cache.__len__

lock = RLock()

root = []

root[:] = [root, root, None, None]

if maxsize == 0:

def wrapper(*args, kwds):

nonlocal misses # 要改变misses,所以用nonlocal声明

misses += 1

result = user_function(*args, kwds)

return result

elif maxsize is None:

def wrapper(*args, kwds):

# Simple caching without ordering or size limit

nonlocal hits, misses

key = make_key(args, kwds, typed)

result = cache_get(key, sentinel)

if result is not sentinel:

hits += 1

return result

misses += 1

result = user_function(*args, kwds)

cache[key] = result

return result

else:

def wrapper(*args, kwds):

# Size limited caching that tracks accesses by recency

nonlocal root, hits, misses, full

key = make_key(args, kwds, typed)

with lock:

link = cache_get(key)

if link is not None:

# Move the link to the front of the circular queue

link_prev, link_next, _key, result = link

link_prev[NEXT] = link_next

link_next[PREV] = link_prev

last = root[PREV]

last[NEXT] = root[PREV] = link

link[PREV] = last

link[NEXT] = root

hits += 1

return result

misses += 1

result = user_function(*args, kwds)

with lock:

if key in cache:

# Getting here means that this same key was added to the

# cache while the lock was released. Since the link

# update is already done, we need only return the

# computed result and update the count of misses.

pass

elif full:

# Use the old root to store the new key and result.

oldroot = root

oldroot[KEY] = key

oldroot[RESULT] = result

# Empty the oldest link and make it the new root.

# Keep a reference to the old key and old result to

# prevent their ref counts from going to zero during the

# update. That will prevent potentially arbitrary object

# clean-up code (i.e. __del__) from running while we’re

# still adjusting the links.

root = oldroot[NEXT]

oldkey = root[KEY]

oldresult = root[RESULT]

root[KEY] = root[RESULT] = None

# Now update the cache dictionary.

del cache[oldkey]

# Save the potentially reentrant cache[key] assignment

# for last, after the root and links have been put in

# a consistent state.

cache[key] = oldroot

else:

# Put result in a new link at the front of the queue.

last = root[PREV]

link = [last, root, key, result]

last[NEXT] = root[PREV] = cache[key] = link

# Use the cache_len bound method instead of the len() function

# which could potentially be wrapped in an lru_cache itself.

full = (cache_len() >= maxsize)

return result

def cache_info():

“””Report cache statistics”””

with lock:

return _CacheInfo(hits, misses, maxsize, cache_len())

def cache_clear():

“””Clear the cache and cache statistics”””

nonlocal hits, misses, full

with lock:

cache.clear()

root[:] = [root, root, None, None]

hits = misses = 0

full = False

wrapper.cache_info = cache_info

wrapper.cache_clear = cache_clear

return wrapper

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232874.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 微信小程序开发环境(阿里云服务搭建+可运行的demo)「建议收藏」

    最近微信小程序异常火爆,很多人在学习,下面带着大家搭建下微信小程序的调试环境(client+server),并调试一套demo源码(JavaScript和node.js基础即可,微信推荐使用的语言,无前端编程基础,去菜鸟教程简单学习下JavaScript,node.js,mysql即可),方便大家学习。微信小程序搭建环境必需的两点:云服务器,域名,下面一步步给搭建演示如果在一台阿里云服…

    2022年4月16日
    118
  • 由华为裁员传闻引发的思考:年轻人如何避免中年危机?「建议收藏」

    由华为裁员传闻引发的思考:年轻人如何避免中年危机?「建议收藏」看到这个话题,让我想起来之前在知乎上看到的一句话,找了半天当时的截图,没找到。最后在QQ留言板上找到了:这句话确实是让人细思极恐,时间再也没有童年那么漫长了,变得越来越快。20岁时,你可以没有钱,买不起iphone4送给女朋友。总说莫欺少年穷,是因为你有大把的未来去提高自己,同时提高自己的经济实力。不然的话。30岁时,你舍不得给老婆买iphone8。40岁时,你的妻子就会因为压力迅速苍老,然后你的…

    2022年7月18日
    40
  • 阿里云 analyticdb_阿里云数据库在哪里

    阿里云 analyticdb_阿里云数据库在哪里AnalyticDB全面兼容MySQL协议和SQL2003,基本上可以像MySQL一样使用它。现在重点看看它们有什么区别。一、与MySQL数据类型对比AnalyticDB数据类型MySQL数据类型差异booleanbool、boolean一致tinyinttinyint一致smallintsmallint一致intint、integer…

    2022年9月17日
    2
  • linux0.11_linux常用命令

    linux0.11_linux常用命令前言所有的UnixLike系统都会内建vi文书编辑器,其他的文书编辑器则不一定会存在。但是目前我们使用比较多的是vim编辑器。vim具有程序编辑的能力,可以主动的以字体颜色辨别语法的

    2022年7月29日
    5
  • ubuntu 卸载软件命令及方法[通俗易懂]

    ubuntu 卸载软件命令及方法[通俗易懂]1、如果是从UbuntuSoftwareCenter安装的,进入center,找到那个软件,很明显会有“卸载”的按钮;2、如果是tar、gz、zip之类解压就能用,免安装的,直接删除;3、如果是自己下载的deb包安装,或者通过apt-getinstall安装、或者通过添加ppa安装,使用sudoapt-getautoremovesoftware-name来卸载,为了一次卸干净,可以

    2022年10月5日
    2
  • 网络编程——UDP编程

    网络编程——UDP编程一、网络编程基础1.常用协议:IP协议;TCP协议;UDP协议;2.什么是Socket?二、服务器端的代码实现三、客户端的代码实现1.区别2.易混淆知识点四.代码实现五.最后小结

    2025年10月8日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号