Как функция обрабатывает глобальные объекты в Python?Что такое порядок исполнения? - PullRequest
1 голос
/ 29 марта 2019

Я относительно новичок в Python, и я играл со следующим примером в matplotlib (https://matplotlib.org/examples/widgets/slider_demo.html).

Я изменил приведенный выше пример следующим образом (и он все еще работает), как и предполагалось (по крайней мере, насколько мне известно)

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()

По сути, все, что я сделал, - это разделил функции. Однако я не могу понять, как функция обновления «знает», что такое объекты samp и sfreq?

Поскольку это работает, я вижу только следующую опцию, что функции каждый раз будут запрашивать «глобальные» объекты для их текущих значений. Тем не менее, это кажется мне особенно подверженным ошибкам, так как samp и sfreq могут меняться между выполнениями обновления.

Итак, вероятно, вопрос в том, когда я использую

sfreq.on_changed(update)

и при установке обратного вызова события ссылки на глобальные объекты становятся фиксированными или переоцениваются при каждом вызове функции. Или что-то еще полностью происходит?

Отказ от ответственности: Это связано с вопросом Порядок исполнения и стиль кодирования в Python , однако есть небольшие различия.

1 Ответ

0 голосов
/ 29 марта 2019

Давайте посмотрим на функцию 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()

Каждый раз, когда вы вызываете функции, Python ищет имена, во-первых, в локальном пространстве имен, во-вторых, в глобальном пространстве имен, в-третьих, throwsNameError.Имена val, amp и freq расположены в локальном пространстве имен функции.Python находит их на первом шаге.Локальное пространство имен существует только в то время, когда длится вызов функции.Имена samp, sfreq, l, fig расположены в глобальном пространстве имен.Python находит их на втором шаге.Таким образом, каждый раз, когда fig является одним и тем же объектом, который вы создали со строкой fig, ax = plt.subplots().

Если одно и то же имя находится как в локальных, так и в глобальных пространствах имен, Python выбирает его из локального пространства имен, потому что этопервое место для поиска.

Вы можете получить доступ к содержимому пространств имен с помощью locals() и globals() - функции возвращают словари {"object_name": <object_itself>, ...}.

...