将公式转换为字符串以在Python中起作用

时间:2019-03-03 11:23:35

标签: python function tkinter graph

我对此代码有疑问。 我想向该类发送一个函数(例如: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 :(得分:0)

总的来说,您要寻找的功能是eval()。不幸的是, 这不是安全的功能 。将字符串公式嵌入代码中后,您就可以了,但是一旦您开始通过tkinter Entry框从用户那里获取该字符串,便会遇到问题。您的用户可以输入 任何 并获取您的代码以对其进行评估。例如。允许他们删除您的所有文件。

让它更安全取决于您:您可以扫描字符串以确保它仅包含x和允许的一组运算符;您可以预定义它们可以在dict中绘制的所有公式;等等。有些人可能会声称ast.literal_eval()会解决安全问题-不适用于您的目的。

在小图中,您的__init__函数中有一个错误,因为fkt是一个变量,一个成员和一个< em>方法名称。这样可以防止您的代码运行,因此在下面的代码重做中,我将其中一个重命名为:

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

答案 1 :(得分:0)

非常感谢@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中的字符匹配,如果不匹配,则退出程序。