Почему мой (рабочий) код (который создает интерактивный график) больше не работает при помещении его в функцию?

Я создал интерактивный график с помощью Python, используя matplotlib, и хочу вызвать его, поместив его в функцию. Все работает, пока я не поместил весь свой код в функцию make_plot(). Запуск кода без функции make_plot() дает мне именно то, что я хочу. Почему он больше не работает внутри другой функции (я просто теряю интерактивную функциональность)?

import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import numpy as np

def make_plot():
    def button_clicked(event):
        global line_plotted
        if line_plotted:
            ax1.lines[1].remove()
            line_plotted = False
        else:
            ax1.plot(line[0], line[1], color='r', linestyle='--')
            line_plotted = True
        fig.canvas.draw()
            
    
    plt.ion()
    
    x = np.linspace(0, 4*np.pi, 500)
    y = np.sin(x)
    line = [0, 4 * np.pi], [1, 1]
    
    fig = plt.figure(figsize=(15,5))
    ax1 = fig.add_subplot()
    ax1.plot(x,y)
    ax1.plot(line[0], line[1], color='r', linestyle='--')
    line_plotted = True
    
    button_ax = plt.axes([0.8, 0.05, 0.1, 0.075])
    button = Button(button_ax, 'Show red line')
    button.on_clicked(button_clicked)
    
    
    
    plt.show()

make_plot()

Я попытался поместить функцию button_clicked(event) вне функции make_plot(), но это не помогло.

Строка global line_plotted предполагает, что есть еще код, который вы нам не показываете. Предположительно, проблема в том, что в вашей функции изменяются глобальные переменные. Пожалуйста, отредактируйте и поделитесь минимально воспроизводимым примером.

Friedrich 07.05.2024 12:07

что такое Button? это от matplotlib.widgets? Пожалуйста, включите импорт, чтобы мы знали, какие библиотеки вы используете.

Elerium115 07.05.2024 12:18

Что решило мою конкретную проблему, так это изменить глобальный -> нелокальный и добавить строку «x = input()» ниже «plt.show()». Это дает мне желаемый результат, когда я запускаю программу с терминала (на Mac просто набираю «python <имя файла>»). Но когда я запускаю код напрямую из Spyder, он все равно не работает. Теперь мне было бы просто интересно, почему он работает с терминала, а не со Spyder.

Gape 07.05.2024 12:33

Теперь кажется, что это было сделано неправильно. Использование команды input() только для удержания функции кажется «дешевым трюком»…

Gape 07.05.2024 12:36

Если у вас есть еще вопрос, задайте еще вопрос. В вашем первоначальном вопросе ничего не говорилось о Spyder, поэтому вы не можете рассчитывать на ответы о Spyder. И на ваш новый вопрос, возможно, уже был дан ответ; воспользуйтесь поиском этого сайта.

Friedrich 07.05.2024 12:39

Да, технически, на мой первоначальный вопрос не был дан ответ... Почему я теряю интерактивную функциональность при помещении кода внутрь функции?

Gape 07.05.2024 15:32
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
6
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
global line_plotted

-->

nonlocal line_plotted

После перемещения всего кода внутри функции line_plotted не находится на глобальном уровне, ключевое слово nonlocal используется для ссылки на переменную в ближайшей области видимости.

Обновлено: полный код

запустите в pycharm и spyder, все они интерактивны — нажмите кнопку.

import matplotlib
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import numpy as np

matplotlib.use("TkAgg")


def make_plot():
    def button_clicked(event):
        nonlocal line_plotted
        if line_plotted:
            ax1.lines[1].remove()
            line_plotted = False
        else:
            ax1.plot(line[0], line[1], color = "r", linestyle = "--")
            line_plotted = True
        fig.canvas.draw()

    plt.ion()

    x = np.linspace(0, 4 * np.pi, 500)
    y = np.sin(x)
    line = [0, 4 * np.pi], [1, 1]

    fig = plt.figure(figsize=(15, 5))
    ax1 = fig.add_subplot()
    ax1.plot(x, y)
    ax1.plot(line[0], line[1], color = "r", linestyle = "--")
    line_plotted = True

    button_ax = plt.axes([0.8, 0.05, 0.1, 0.075])
    button = Button(button_ax, "Show red line")
    button.on_clicked(button_clicked)

    plt.show(block=True)


make_plot()

При внесении этого изменения сюжет по-прежнему не является интерактивным.

Gape 07.05.2024 15:41

Я тестирую полный код, запускаю его в pycharm и spyder. Некоторые различия с вашим исходным кодом.

ACE Fly 07.05.2024 16:40

Да, это оно. matplotlib.use("TkAgg") в моем случае не нужен, но блок=True внутри plt.show() заставляет его работать по мере необходимости. Спасибо!

Gape 08.05.2024 08:43

Другие вопросы по теме