Преобразовать формулу в строку как функцию в Python - PullRequest
0 голосов
/ 03 марта 2019

У меня проблема с этим кодом.Я хочу послать функцию (например: x ** 2) в этот класс, чтобы он показал мне ее график.Вот что у меня получилось:

import tkinter as tk

class diagram(tk.Frame):
    step=100
    point_lst=[]
    def __init__(self, master=None, fkt="x**2"):
        self.fkt=fkt
        super().__init__(master)
        self.pack()
        self.cv=tk.Canvas(self, width=600, height=600, bg="#F00011")
        self.cv.pack()
        self.update_scale()
        self.fkt()

    def fkt(self):
        for x in range(0, 100):
            self.point_lst.append((x+10, self.fkt+10))

        print(self.point_lst)

        for i in range(1, 99, 1):
            self.cv.create_line(self.point_lst[i-1][0], 600-self.point_lst[i-1][1], self.point_lst[i][0], 600-self.point_lst[i][1])

    def update_scale(self):
        #print("up")
        self.cv.delete(tk.ALL)

        self.cv.create_line(10, 590, 590, 590, width=3)
        self.cv.create_line(10, 10, 10, 590, width=3)
        #scale on bot
        for x in range(10, 590, self.step):
            self.cv.create_line(x, 590, x, 580)
        #scale on side
        for y in range(10, 590, self.step):
            self.cv.create_line(10, y, 20, y)


root=tk.Tk()
app=diagram(root)
app.mainloop()

Проблема в методе fkt(), где он должен добавлять точки в список self.point_lst.Как я могу добиться, чтобы он вычислял заданную функцию?

PS: +10, которые я добавил, для графических причин.Вы можете игнорировать это.

Ответы [ 2 ]

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

Большое спасибо @cdlane, это сработало замечательно!

Я также добавил функцию для проверки допустимых символов:

   def check_str(self):
        for char in self.fkt_string:
            if char not in self.allowed_str:
                print("Warning! Some of the strings may not be allowed")
                quit()

Проверяет, есть ли символы в данной формулесовпадать с символами в self.fkt_string, и если нет, то выходит из программы.

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

На большом изображении вы ищете функцию eval().К сожалению, это не безопасная функция .Со встроенной в ваш код строковой формулой все в порядке, но как только вы начнете получать эту строку от пользователя через окно tkinter Entry, у вас возникнет проблема.Ваш пользователь может набрать что угодно и получить код для его оценки.Например, разрешите им удалить все ваши файлы.

Обеспечение большей безопасности зависит от вас: вы можете сканировать строку, чтобы убедиться, что она содержит только x и разрешенный набор операторов;вы можете заранее определить все формулы, которые они могут отобразить в dict;и т. д. Некоторые люди могут утверждать, что ast.literal_eval() позаботится о безопасности - это не сработает для ваших целей.

На небольшом рисунке вы обнаружили ошибку в вашей функции __init__fkt - это переменная , член и имя метода .Это не позволяет вашему коду работать, поэтому я переименовал один из них в мою переработку кода ниже:

import tkinter as tk

class diagram(tk.Frame):
    STEP = 100
    WIDTH = 600
    HEIGHT = 600
    BORDER = 15
    TICK = 10

    def __init__(self, master=None, fkt="2 * x"):
        super().__init__(master)

        self.fkt_string = fkt
        self.cv = tk.Canvas(self, width=self.WIDTH + self.BORDER, height=self.HEIGHT + self.BORDER, bg="#FFAAAA")
        self.cv.pack()
        self.pack()
        self.update_scale()
        self.fkt()

    def fkt(self):
        point_lst = []

        for x in range(0, 100):
            point_lst.append((x + self.BORDER, self.HEIGHT - eval(self.fkt_string)))

        for i in range(1, 100):
            self.cv.create_line(point_lst[i - 1][0], point_lst[i - 1][1], point_lst[i][0], point_lst[i][1])

    def update_scale(self):
        self.cv.delete(tk.ALL)

        self.cv.create_line(self.BORDER, self.HEIGHT, self.WIDTH + self.BORDER, self.HEIGHT, width=3)
        self.cv.create_line(self.BORDER, self.HEIGHT, self.BORDER, 0, width=3)

        # scale on bottom
        for x in range(self.BORDER, self.WIDTH + self.BORDER, self.STEP):
            self.cv.create_line(x, self.HEIGHT, x, self.HEIGHT - self.TICK)

        # scale on side
        for y in range(self.HEIGHT, 0, -self.STEP):
            self.cv.create_line(self.BORDER, y, self.BORDER + self.TICK, y)

root = tk.Tk()
app = diagram(root)
app.mainloop()

График "2 * x":

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...