global and nonlocal scope instance problems in Python

There are countless online explanations about the scope of global and nonlocal in Python. Let me take an example in practice to deepen the impression of Python scope knowledge.

The reason is this: I want to launch GUI interface to let customers choose some activities, and serialize the user's choices to local, and at the same time, I want to continue to remember the user's choices in memory, so that I can continue to use them later.

import pickle
import tkinter
app = tkinter.Tk()

def selenium_handler_yingxiao():
    all_activity_name = ["Xi'an guest economy-Smart enterprise-Community Shop dispatch list",
                         "2020 Xi'an community store-Single wide to financial marketing",
                         "Xi'an community store-Collection of arrears with account age of 2 months"]
    try:
        activity_record = pickle.load(open('4to5.pckl', 'rb'))
    except FileNotFoundError:  # If the file does not exist, create and reset
        print("File does not exist, new and reset")
        activity_record = []
    if len(activity_record) == 0:  # If the read content is empty, open the GUI for setting
        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("The activity we want to call is 1:", id(activity_record), activity_record)
            app.quit()

        tkinter.Button(app, text="confirm", command=change).pack()
        app.mainloop()

    print("The activities we want to call are 2:", id(activity_record), activity_record)

selenium_handler_yingxiao()
print("The activities we want to call are:", id(activity_record), activity_record)

                                                     

 

I expect the output of both activities to be the same, but the actual output is as follows:

The activities we would like to call are 1:318160520 ['2020 Xi'an community store - Shan Kuan transfer to financing marketing ',' Xi'an community store - overdue payment recovery with aging of 2 months']
The activity we want to call is 2:318517960 []
The activities we would like to call are: 318160520 ['2020 Xi'an community store - Shan Kuan to finance marketing ','xi'an community store - overdue payment recovery for 2 months']

Why does this happen?

This is because of the global activity in the function change()_ Record statement changes the variable activity_record is declared as a global variable, but as long as it is still in the function selenium_ handler_ In the scope of yingxiao(), activity_record is still selenium_ handler_ The local variable of the yingxiao() function. In selenium_ handler_ Beyond the scope of the yingxiao() function, we can still get the user's selection normally.

So, if we want to use the function selenium_ handler_ At the end of yingxiao(), you can get the activity selected by the user normally. What should you do?

The first way: we can_ handler_ The variable activity is declared in the yingxiao() function_ Record is the global activity_record), so global activity is declared in two places_ record,selenium_ handler_ The variables in yingxiao () become real global variables.

import pickle
import tkinter
app = tkinter.Tk()

def selenium_handler_yingxiao():
    global activity_record
    all_activity_name = ["Xi'an guest economy-Smart enterprise-Community Shop dispatch list",
                         "2020 Xi'an community store-Single wide to financial marketing",
                         "Xi'an community store-Collection of arrears with account age of 2 months"]
    try:
        activity_record = pickle.load(open('4to5.pckl', 'rb'))
    except FileNotFoundError:  # If the file does not exist, create and reset
        print("File does not exist, new and reset")
        activity_record = []
    if len(activity_record) == 0:  # If the read content is empty, open the GUI for setting
        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("The activity we want to call is 1:", id(activity_record), activity_record)
            app.quit()

        tkinter.Button(app, text="confirm", command=change).pack()
        app.mainloop()

    print("The activities we want to call are 2:", id(activity_record), activity_record)

selenium_handler_yingxiao()
print("The activities we want to call are:", id(activity_record), activity_record)
File does not exist, new and reset
 The activities we would like to call are 1:68402824 ['2020 Xi'an community store - Shan Kuan transfer to financing marketing ',' Xi'an community store - overdue payment recovery with aging of 2 months']
The activities we would like to call are 2:68402824 ['2020 Xi'an community store - Shan Kuan transfer to financing marketing ',' Xi'an community store - overdue payment recovery for 2 months']
The activities we would like to call are: 68402824 ['2020 Xi'an community store - Shan Kuan transfer to financing marketing ',' Xi'an community store - overdue payment recovery for 2 months']

Second method: we can declare non local activity in function change()_ Record, in this way, the variable activity declared by nonlocal_ Record is neither a local variable nor a global variable, but an external nested function selenium_ handler_ The variables in yingxiao (), that is, after you declare them like this, you can think of selenium_ handler_ Activity of yingxiao()_ Activity of record and inner nested function change()_ Record is the same variable.

import pickle
import tkinter
app = tkinter.Tk()

def selenium_handler_yingxiao():
    all_activity_name = ["Xi'an guest economy-Smart enterprise-Community Shop dispatch list",
                         "2020 Xi'an community store-Single wide to financial marketing",
                         "Xi'an community store-Collection of arrears with account age of 2 months"]
    try:
        activity_record = pickle.load(open('4to5.pckl', 'rb'))
    except FileNotFoundError:  # If the file does not exist, create and reset
        print("File does not exist, new and reset")
        activity_record = []
    if len(activity_record) == 0:  # If the read content is empty, open the GUI for setting
        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("The activity we want to call is 1:", id(activity_record), activity_record)
            app.quit()

        tkinter.Button(app, text="confirm", command=change).pack()
        app.mainloop()

    print("The activities we want to call are 2:", id(activity_record), activity_record)

selenium_handler_yingxiao()
# print("the activity we want to call is:", id(activity_record), activity_record)
The activities we would like to call are 1:317439688 ['2020 Xi'an community store - Shan Kuan transfer to financing marketing ',' Xi'an community store - overdue payment recovery with aging of 2 months']
The activities we would like to call are 2:317439688 ['2020 Xi'an community store - Shan Kuan transfer to financing marketing ',' Xi'an community store - overdue payment recovery with aging of 2 months']

Of course, at this time, if no special return operation is carried out, in selenium_ handler_ Outside of the yingxiao() function, the activity cannot be obtained_ Of the record variable.

Tags: Python

Posted on Thu, 04 Jun 2020 22:06:39 -0400 by m00ch0