博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python 中的 global 和 nonlocal 作用域实例问题
阅读量:4229 次
发布时间:2019-05-26

本文共 5000 字,大约阅读时间需要 16 分钟。

网上关于Python当中global和nonlocal的作用域讲解已经数不胜数了 ,我就拿个实际当中遇到的例子来说事儿,从而来加深一下Python作用域方面知识的印象。

起因是这样的:我想启动GUI界面让客户选择一些活动,并把用户的选择序列化到本地,同时还希望继续在内存当中记住用户的选择,以便后续继续使用。

import pickleimport tkinterapp = tkinter.Tk()def selenium_handler_yingxiao():    all_activity_name = ["西安客经-智慧企业-社区店派单",                         "2020西安社区店-单宽转融营销",                         "西安社区店-账龄2个月欠费回收"]    try:        activity_record = pickle.load(open('4to5.pckl', 'rb'))    except FileNotFoundError:  # 如果文件不存在,新建并重置        print("文件不存在,新建并重置")        activity_record = []    if len(activity_record) == 0:  # 如果读取内容为空,打开GUI进行设置        op_mark = [tkinter.IntVar() for _ in all_activity_name]        for variable, text in zip(op_mark, all_activity_name):            tkinter.Checkbutton(text=text, variable=variable).pack()        def change():            global activity_record            activity_record = [text for variable, text in zip(op_mark, all_activity_name) if variable.get()]            pickle.dump(activity_record, open('4to5.pckl', 'wb'))            print("我们要呼的活动为1:", id(activity_record), activity_record)            app.quit()        tkinter.Button(app, text="确认", command=change).pack()        app.mainloop()    print("我们要呼的活动为2:", id(activity_record), activity_record)selenium_handler_yingxiao()print("我们要呼的活动为:", id(activity_record), activity_record)

                                                     

 

我期望两个活动输出的东西都是一样的,但是实际输出却是这样的:

我们要呼的活动为1: 318160520 ['2020西安社区店-单宽转融营销', '西安社区店-账龄2个月欠费回收']我们要呼的活动为2: 318517960 []我们要呼的活动为: 318160520 ['2020西安社区店-单宽转融营销', '西安社区店-账龄2个月欠费回收']

为什么会出现这种情况呢?

这是因为函数 change() 中  global activity_record  语句将变量 activity_record 声明为全局变量,但是只要还是在函数selenium_handler_yingxiao() 的作用域里边,activity_record就仍然是 selenium_handler_yingxiao() 函数的局部变量。在 selenium_handler_yingxiao()函数的作用范围以外,我们仍然可以正常获取到用户的选择。

那么,如果我们想在函数 selenium_handler_yingxiao()末尾正常获取到用户选择的活动,应该要怎么做呢?

第一种方法:我们可以在 selenium_handler_yingxiao() 函数里边声明变量 activity_record 为全局变量(global activity_record),这样,就在两处地方声明了global activity_record,selenium_handler_yingxiao()里的变量就变成真正的全局变量了。

import pickleimport tkinterapp = tkinter.Tk()def selenium_handler_yingxiao():    global activity_record    all_activity_name = ["西安客经-智慧企业-社区店派单",                         "2020西安社区店-单宽转融营销",                         "西安社区店-账龄2个月欠费回收"]    try:        activity_record = pickle.load(open('4to5.pckl', 'rb'))    except FileNotFoundError:  # 如果文件不存在,新建并重置        print("文件不存在,新建并重置")        activity_record = []    if len(activity_record) == 0:  # 如果读取内容为空,打开GUI进行设置        op_mark = [tkinter.IntVar() for _ in all_activity_name]        for variable, text in zip(op_mark, all_activity_name):            tkinter.Checkbutton(text=text, variable=variable).pack()        def change():            global activity_record            activity_record = [text for variable, text in zip(op_mark, all_activity_name) if variable.get()]            pickle.dump(activity_record, open('4to5.pckl', 'wb'))            print("我们要呼的活动为1:", id(activity_record), activity_record)            app.quit()        tkinter.Button(app, text="确认", command=change).pack()        app.mainloop()    print("我们要呼的活动为2:", id(activity_record), activity_record)selenium_handler_yingxiao()print("我们要呼的活动为:", id(activity_record), activity_record)
文件不存在,新建并重置我们要呼的活动为1: 68402824 ['2020西安社区店-单宽转融营销', '西安社区店-账龄2个月欠费回收']我们要呼的活动为2: 68402824 ['2020西安社区店-单宽转融营销', '西安社区店-账龄2个月欠费回收']我们要呼的活动为: 68402824 ['2020西安社区店-单宽转融营销', '西安社区店-账龄2个月欠费回收']

第二种方法:我们可以在函数 change() 里声明 nonlocal activity_record,这样,nonlocal声明的变量activity_record不是局部变量,也不是全局变量,而是外部嵌套函数 selenium_handler_yingxiao() 内的变量,也就是说,这样声明以后,你可以认为 selenium_handler_yingxiao() 的 activity_record 和内部嵌套函数 change() 的  activity_record 是同一个变量。

import pickleimport tkinterapp = tkinter.Tk()def selenium_handler_yingxiao():    all_activity_name = ["西安客经-智慧企业-社区店派单",                         "2020西安社区店-单宽转融营销",                         "西安社区店-账龄2个月欠费回收"]    try:        activity_record = pickle.load(open('4to5.pckl', 'rb'))    except FileNotFoundError:  # 如果文件不存在,新建并重置        print("文件不存在,新建并重置")        activity_record = []    if len(activity_record) == 0:  # 如果读取内容为空,打开GUI进行设置        op_mark = [tkinter.IntVar() for _ in all_activity_name]        for variable, text in zip(op_mark, all_activity_name):            tkinter.Checkbutton(text=text, variable=variable).pack()        def change():            nonlocal activity_record            activity_record = [text for variable, text in zip(op_mark, all_activity_name) if variable.get()]            pickle.dump(activity_record, open('4to5.pckl', 'wb'))            print("我们要呼的活动为1:", id(activity_record), activity_record)            app.quit()        tkinter.Button(app, text="确认", command=change).pack()        app.mainloop()    print("我们要呼的活动为2:", id(activity_record), activity_record)selenium_handler_yingxiao()# print("我们要呼的活动为:", id(activity_record), activity_record)
我们要呼的活动为1: 317439688 ['2020西安社区店-单宽转融营销', '西安社区店-账龄2个月欠费回收']我们要呼的活动为2: 317439688 ['2020西安社区店-单宽转融营销', '西安社区店-账龄2个月欠费回收']

当然,这个时候,如果没有进行特别的return操作,在 selenium_handler_yingxiao() 函数外边是获取不到activity_record 变量的。

转载地址:http://edjqi.baihongyu.com/

你可能感兴趣的文章
Telecom for Dummies
查看>>
ASP.NET 2.0 Illustrated
查看>>
PHP 5 in Practice
查看>>
Visual Studio .NET: The .NET Framework Black Book
查看>>
Sams Teach Yourself SAP in 24 Hours (2nd Edition)
查看>>
Ant Developer's Handbook
查看>>
Best Kept Secrets in .NET
查看>>
The Project Management Question and Answer Book
查看>>
Special Edition Using Crystal Reports 10
查看>>
SQL: The Complete Reference
查看>>
Advances In Uml And Xml-based Software Evolution
查看>>
Successful Software Reengineering
查看>>
Wireless Network Hacks & Mods For Dummies
查看>>
Programming INDIGO
查看>>
System Analysis, Design, and Development: Concepts, Principles, and Practices
查看>>
How to Run Successful Projects in Web Time
查看>>
Sams Teach Yourself SQL Server(TM) 2005 Express in 24 Hours
查看>>
Beginning Apache Struts: From Novice to Professional
查看>>
Expert Spring MVC and Web Flow (Expert)
查看>>
A Developer's Guide to SQL Server 2005
查看>>