python2 nonlocal_python unboundlocalerror

python2 nonlocal_python unboundlocalerror在廖雪峰的官网上看到一个很有意思题目。关于闭包的,有兴趣的朋友可以看一下这里,做一下这个题目,当然需要一点闭包的知识。下面我简述一下:利用闭包返回一个计数器函数,每次调用它返回递增整数。#修改下面这个函数defcreateCounter():defcounter():passreturncounter#测试:counterA=createCounter()print(counter…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

在廖雪峰的官网上看到一个很有意思题目。关于闭包的,有兴趣的朋友可以看一下这里, 做一下这个题目,当然需要一点闭包的知识。下面我简述一下:

利用闭包返回一个计数器函数,每次调用它返回递增整数。

# 修改下面这个函数

def createCounter():

def counter():

pass

return counter

# 测试:

counterA = createCounter()

print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5

counterB = createCounter()

if [counterB(), counterB(), counterB(), counterB()] == [1, 2, 3, 4]:

print(‘测试通过!’)

else:

print(‘测试失败!’)

方法一

说实话这题对我来说还是有点难度的,但我尝试了几次之后也找到一个比较track的方法。一开始我是这么写的。

def createCounter():

i = 0

def counter(i=i):

i = i+1

return i

return counter

# 执行结果是: 1 1 1 1 1

这样当然是错的, 因为整数 是 不可变对象,当你作为参数传进去时都会创建一个新的内存空间,这里边其实还有很多学问,不是很了解的可以看一下stackoverflow上的这个回答。虽然失败了,但也让我想到一个track的方法,就是把i换成可变对象

def createCounter():

i = [0]

def counter():

i[0] = i[0]+1

return i[0]

return counter

# 执行结果是: 1 2 3 4 5

OK, 这样就没有问题了。但这并不是一个好的解决方法, 利用可变对象的这个特性有可能会引起变量作用域混乱的。于是我又想到了另一种解决。

方法二

另一种方法就是使用generator,在createCounter函数下创建一个从1开始的整数generator, 然后在cuonter函数中调用。由于generator保存的是算法,当调用next函数时就可以计算出下一个的值,直到没有元素报错。当然这里不用担心,generator可以创建无限集合。

def createCounter():

def inter():

n = 1

while True:

yield n

n = n+1

f = inter()

def counter():

return next(f)

return counter

上面的代码中,inter()就是一个包含从1开始的所有整数的generator。然后在counter里边调用。每次计算下一个的值。这样就可以实现计数的功能。说到generator,stackoverflow上有一个回答值得一读,即使你已经掌握这个也可以读一下,这个回答应该还是python问答当中排名第一的。链接在这里。

方法三

emmmm,想到这两种方法已经是极限了,于是我往评论区翻了翻,看一下大佬们有什么做法。然后就看到一个我没见过的关键字…其中有一个大佬是这么做

def creat_counter():

i=0

def counter():

nonlocal i

i=i+1

return i

return counter

学了python这么久,第一次看到nonlocal这个关键字,果然我还是太菜了。。。

不过从语句上看nonlocal的作用应该是把i变成全局变量,这样每次修改都可以生效,跟global关键字有点像。既然找到一个知识盲点,那就将它彻底解决吧。

nonlocal 与 global

说了这么多,是时候回到主题了,nonlocal关键字到底是什么?在什么情况下用呢?简单来说,nonlocal关键字是用来改变变量的作用域的,直接解释不太好懂。先来看两个例子吧。

def outside():

msg = “Outside!”

def inside():

msg = “Inside!”

print(msg)

inside()

print(msg)

执行结果是什么呢?

Inside!

Outside!

结果应该很好理解, 在outside函数里面定义了inside函数并且执行。当运行outside函数时,inside里面的msg变量指向了”Inside!”,outside里面的msg指向了”Outside!”, 也就是说这里其实有两个msg变量,并且指向了不同的值。如下图所示:

python2 nonlocal_python unboundlocalerror

变量示意图

再来看下面这个例子:

def outside():

msg = “Outside!”

def inside():

nonlocal msg

msg = “Inside!”

print(msg)

inside()

print(msg)

现在的执行结果就变成了:

Inside!

Inside!

两段代码之间的差别仅在于下面的例子多了一句 nonlocal msg。这里的nonlocal关键字起到了什么作用呢?nonlocal意思是告诉python,不要重新创建msg变量,而是使用outside中的msg变量来赋值。画个图就很好懂了。

python2 nonlocal_python unboundlocalerror

变量示意图

在这个例子中, msg变量只被创建了一次,首先将”Outside!”赋值给msg,然后将”Inside!”赋值给了msg, 此时的msg已经指向了”Inside!”。因此执行的结果两个都是”Inside!”。

现在我们知道了,nonlocal是用来改变变量的作用域的。本例中,nonlocal将inside函数里面的msg变量的作用域变成了outside块中的区域。nonlocal跟global 这两个关键字非常像,不同之处在于nonlocal用于外部函数作用域的变量,而global用于全局范围内的变量。

这就是nonlocal关键字的作用。但是还有一点值得注意,先看下面的例子。

def outside():

d = {“outside”: 1}

def inside():

d[“inside”] = 2

print(d)

inside()

print(d)

大家觉得输出是什么呢?

实际输出是这样的:

{‘outside’: 1, ‘inside’: 2}

{‘outside’: 1, ‘inside’: 2}

原因嘛,当然是因为dict是可变对象了,但由于 d[“inside”] = 2 这样的语句是有点让人迷惑的,看起来很像重新赋值。实际上dict的赋值是调用了setitem方法。这样看就不会感到迷惑了。

# 下面的代码是等价的。

d[“inside”] = 2

d.__setitem__(“inside”, 2)

关于nonlocal关键字,应该讲清楚了吧。至于python的闭包,其实还是挺复杂的,上面的只是几个例子,想要更加深入的学习可以上stackoverflow上看看大佬们的回答。很有学习的价值。

写文不易, 还请大家多多支持!

参考资料:

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

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

(0)
上一篇 2025年9月21日 下午3:15
下一篇 2025年9月21日 下午3:43


相关推荐

  • ODS与EDW的区别「建议收藏」

    ODS与EDW的区别「建议收藏」根据自己的理解与实际项目经验,说说ODS与EDW的异同。如果有不对的地方,欢迎大家批评指正。维基百科对于ODS的定义为”Anoperationaldatastore(or“ODS”)isadatabasedesignedtointegratedatafrommultiplesourcesforadditionaloperationsonthedata.Un

    2026年4月14日
    3
  • 互联网金融风控模型「建议收藏」

    互联网金融风控模型「建议收藏」一、市场调研目前市面主流的风控模型1、互联网金融前10名排行榜(数据截止日期2017-09-12)互联网金融公司排名分别是蚂蚁金服、陆金所、京东金融、苏宁金融、百度金融、腾讯理财通、宜信、钱大掌柜、万达金融和网易理财。1.1蚂蚁金服1.1.1大数据技术对接第三方征信公司芝麻信用分,通过用户信用历史、行为偏好、履约能力、身份特质、人脉关系五个维度对…

    2022年6月14日
    35
  • 让引擎不再是你的唯一,对百度再见

    让引擎不再是你的唯一,对百度再见

    2022年1月12日
    46
  • SeaWeedFS的特性

    SeaWeedFS的特性1 默认 master 服务器与 volume 服务器之间的 heartbeat 时间是 5s2 seaweedfs 中的名词简介 master 存储文件和 fid 映射关系 volumn 实际存储文件 datacenter 数据中心 rack 机架 一个机架属于特定的数据中心 一个数据中心可以包含多个机架 collection 一组 volume 的集合 如果在存储文件的时候没有指定 colle

    2026年3月18日
    2
  • ffmpeg的安装_一锁三抽屉安装视频

    ffmpeg的安装_一锁三抽屉安装视频1.FFmpeg介绍FFmpeg是一个完整的、跨平台的解决方案,用于记录、转换和流化音/视频。FFmpeg采用LGPL或GPL许可证,提供了录制、转换及流化音/视频的完整解决方案。其包含了非常先进的音/视频编解码库libavcodec。FFmpeg是在Linux平台下开发的但是它同样也可以在其他操作系统环境中编译运行,包扩Windows、MacOS等系统。这个项目最早是由FabriceBellard发起的,在2004年至2015年由MichaelNiedermay

    2025年11月8日
    4
  • linux redis命令客户端,Redis客户端

    linux redis命令客户端,Redis客户端Redis客户端Redis客户端是一个程序,通过网络连接到Redis服务器,在客户端软件中使用Redis可以识别的命令,向Redis服务器发送命令,告诉Redis想要做什么。Redis把处理结果显示在客户端界面上。通过Redis客户端和Redis服务器交互。Redis客户端发送命令,同时显示Redis服务器的处理结果在Redis命令行客户端redis-cli…

    2022年5月1日
    70

发表回复

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

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