简体   繁体   中英

How do function handle global objects in python? What is the execution order?

I am relatively new in Python, and I was playing around with the following example in matplotlib ( https://matplotlib.org/examples/widgets/slider_demo.html ).

I have modified the above example in the following way (and it still works) as intended (at least to my knowledge)

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons



def update(val):
    amp = samp.val
    freq = sfreq.val
    l.set_ydata(amp*np.sin(2*np.pi*freq*t))
    fig.canvas.draw_idle()

def reset(event):
    sfreq.reset()
    samp.reset()



def colorfunc(label):
    l.set_color(label)
    fig.canvas.draw_idle()


if __name__=='__main__':
    fig, ax = plt.subplots()
    plt.subplots_adjust(left=0.25, bottom=0.25)
    t = np.arange(0.0, 1.0, 0.001)
    a0 = 5
    f0 = 3
    s = a0*np.sin(2*np.pi*f0*t)
    l, = plt.plot(t, s, lw=2, color='red')
    plt.axis([0, 1, -10, 10])

    axcolor = 'lightgoldenrodyellow'
    axfreq = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
    axamp = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=axcolor)

    sfreq = Slider(axfreq, 'Freq', 0.1, 30.0, valinit=f0)
    samp = Slider(axamp, 'Amp', 0.1, 10.0, valinit=a0)

    sfreq.on_changed(update)
    samp.on_changed(update)

    resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
    button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')

    button.on_clicked(reset)

    rax = plt.axes([0.025, 0.5, 0.15, 0.15], facecolor=axcolor)
    radio = RadioButtons(rax, ('red', 'blue', 'green'), active=0)

    radio.on_clicked(colorfunc)

    plt.show()

Essentially, all I've done was that I've separated the functions. However, I can't understand how does the update function 'know' what the samp and sfreq objects are?

Since it works I only see the following option, that the functions every single time will query for the 'global' objects for their current values. However, this seems to me especially error prone, since the samp and sfreq may change between executions of the update.

So, probably the question is when I am using the

sfreq.on_changed(update)

and setting an event callback, the references to the global objects become fixed, or are they reevaluated everytime the function is called. Or does something else entirely happens?

Disclaimer: This is related to the question Order of execution and style of coding in Python however there are subtle differences.

Let's have a look at the function update :

def update(val):
    amp = samp.val
    freq = sfreq.val
    l.set_ydata(amp*np.sin(2*np.pi*freq*t))
    fig.canvas.draw_idle()

Every time you call functions Python searches for names, first, in the local namespace, second, in the global namespace, third, throws NameError . Names val , amp , and freq are located in the local namespace of the function. Python finds them on the first step. Local namespace exists only while fucntion call lasts. Names samp , sfreq , l , fig are located in the global namespace. Python finds them on the second step. So every time fig is the same object you have created with the line fig, ax = plt.subplots() .

If the same name is located in both local and global namespaces Python takes the one from the local namespace because it is the first place to look.

You may access the content of the namespaces with locals() and globals() - functions return dictionaries {"object_name": <object_itself>, ...} .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM