首页 > 编程问答 >在 matplotlib 中绘制一个字符串函数 // 将 str 解释为 python 代码?

在 matplotlib 中绘制一个字符串函数 // 将 str 解释为 python 代码?

时间:2024-07-26 04:23:55浏览次数:9  
标签:python matplotlib

我正在创建一个 RPN 计算器,尝试绘制用户给出的函数。例如,如果用户输入 "x sin 3 * plot" 我希望它绘制 sin(x)*3 其代码如下。注意:问题在 if prompt=="plot"

userInputX=""               #userInputX is always replaced before
                            #running again, so it can be set once here
while True:        
    print("----------------------------------------------------------")
    if not myqueue.isEmpty(): # Display both postfix and infix
        print("Postfix: "+str(myqueue))
        print("Infix: "+StackCalc.postfix2infix(myqueue))
    prompt=input(">")
    if prompt == "exp" or prompt == "^": prompt = "**"  #<- Easiest way to stop errors with eval(),
    if prompt=="quit": break                            #+ consistent formatting while still accepting exp/^

    if prompt=="run":
        if myqueue.find("x") is True:                   # If run, get x value from user, set post2in to the 
            userInputX=input("Enter x value: ")         #result of postfix2infix except replace the x with userinput
        post2in=StackCalc.postfix2infix(myqueue).replace("x",userInputX)
        print("Solution using infix:",eval(post2in))    #then evaluate it
        print("Solution using postfix:",StackCalc.evaluate_postfix(myqueue,userInputX))
        continue #skip to next iteration, as "run" shouldnt be pushed to queue

    if prompt=="plot":
        post2in=StackCalc.postfix2infix(myqueue)
        usrInp=input("Enter values of xmin, xmax, nbp: ")#input format "0.5 10.5 1"
        usrInp=usrInp.split()                       # Make it a list,
        xmin,xmax,nbp=usrInp[0],usrInp[1],usrInp[2] #set values to input
        
        #this is where it gets questionable
        x=np.linspace(float(xmin),float(xmax),int(nbp))
        plt.plot(x,post2in)   # this is specifically where the issue lies
        plt.title("f(x)="+str(post2in))
        plt.show()
        continue # dont push "plot" to queue


    if prompt!="flush":
        if prompt == "exp" or prompt == "^": prompt = "**"
        myqueue.enqueue(prompt)     # same code as optn. 2
    else:
        myqueue.flush()

要明确的是, postfix2infix 以字符串形式返回用户的函数。对于我上面使用的示例,它将返回 "sin(x)*3" 作为字符串,我需要将其解释为函数/python 代码。这可能吗?


可以使用 eval() 函数将字符串作为 Python 代码执行,但是 强烈建议不要使用 eval() 处理用户输入,因为这可能会带来安全风险 。如果用户输入恶意代码, eval() 将会执行它。

更安全的做法是使用 sympy 库解析表达式,然后进行计算和绘图。以下是如何修改代码以使用 sympy

import matplotlib.pyplot as plt
import numpy as np
import sympy

# ... 其他代码 ...

if prompt == "plot":
    post2in = StackCalc.postfix2infix(myqueue)
    usrInp = input("Enter values of xmin, xmax, nbp: ")
    usrInp = usrInp.split()
    xmin, xmax, nbp = float(usrInp[0]), float(usrInp[1]), int(usrInp[2])

    # 使用 sympy 解析表达式
    x = sympy.symbols('x')
    expr = sympy.sympify(post2in)

    # 生成数据用于绘图
    x_vals = np.linspace(xmin, xmax, nbp)
    y_vals = [expr.subs(x, val).evalf() for val in x_vals]

    plt.plot(x_vals, y_vals)
    plt.title("f(x) = " + str(expr))
    plt.show()
    continue

代码解释:

  1. 导入 sympy 库。
  2. 将字符串表达式解析为 sympy 表达式。 sympy.sympify() 函数将字符串转换为 sympy 可以理解的数学表达式。
  3. 使用 subs() evalf() 计算 y 值。
    • expr.subs(x, val) 将表达式中的 x 替换为 x_vals 中的每个值。
    • evalf() 计算替换后的表达式的数值结果。
  4. 使用 matplotlib 绘制图形。

使用示例:

如果用户输入 "x sin 3 * plot" ,代码将会:

  1. 使用 postfix2infix() 函数将后缀表达式转换为中缀表达式 "sin(x)*3"
  2. 使用 sympy.sympify() 将字符串 "sin(x)*3" 解析为 sympy 表达式。
  3. 对于 x_vals 中的每个值,使用 subs() x 替换为该值,然后使用 evalf() 计算表达式的值。
  4. 使用计算出的 x_vals y_vals 绘制图形。

安全建议:

即使使用 sympy ,仍然建议对用户输入进行验证,以确保其是有效的数学表达式。可以使用正则表达式或其他方法来验证输入。

标签:python,matplotlib
From: 78795104

相关文章

  • Python (Pebble) - 超时功能。当 TimeoutError 发生时,获取从 iterable 传递给函数的值
    我正在尝试在Pebble中设置工作超时(基本上有效)frompebbleimportProcessPoolfrommultiprocessingimportProcess,Pool,cpu_countimporttimedeftest_fn(randomNumberFromList):#print(f'Beginngingforthisnumber:{randomNumberFromList}')ifr......
  • 为什么在 Python 上使用正则表达式组功能会给出不同的输出
    importrestring1="aaabaa"zusuchen="aa"#1m_start=re.finditer(fr'(?=({zusuchen}))',string1)results=[(match.start(1),match.end(1)-1)formatchinm_start]forzinresults:print(z)print("Now#2:"......
  • 如何在python3中找到文件的长度?
    我的第一个.py:defcreate_file(file_name):list=["ab","cd","ef"]foriinlist:withopen(file_name,"a+")asinput_file:print("{}".format(i),file=input_file)我的第二个.py:fromfirstimport......
  • 哪种 python 日志记录风格是推荐的或标准的?
    我是Python新手。介于以下2个选项之间。对于python来说,推荐哪种风格或者更好?logging.info(f"Won'tsavemodelasscoreisbelow0,score:{score}")logging.info("Won'tsavemodelasscoreisbelow0,score%s",score)我个人更喜欢第二种方法。在Python......
  • python 协程 自定义互斥锁
    最近在用python的一款异步web框架sanic搭建web服务,遇到一个需要加特定锁的场景:同一用户并发处理订单时需要排队处理,但不同用户不需要排队。如果仅仅使用asyncwithasyncio.Lock()的话。会使所有请求都排队处理。1importasyncio2importdatetime34lock=asyncio.L......
  • Python 获取tiktok视频评论回复数据 api接口
    TIKTOKapi接口爬取tiktok视频评论回复数据详细采集页面如图https://www.tiktok.com/@dailymail/video/7329872821990182190?q=neural%20link&t=1706783508149请求APIhttp://api.xxxx.com/tt/video/info/comment/reply?video_id=7288909913185701125&comment_id=7294900......
  • Shopee虾皮api python获取虾皮购物平台的商品数据信息 数据采集
    虾皮购物(英语:Shopee)是一个电商平台,总公司设在新加坡,归属于SeaGroup(之前称之为Garena),该企业于2009年由李小冬(ForrestLi)创办。虾皮购物于2015年初次在新加坡推出,现阶段已拓展到马来西亚、泰国、印度尼西亚、越南和菲律宾。虾皮购物为全球华人地区的客户提供线上购物和销售......
  • python实现图像特征提取算法1
    python实现Marr-Hildreth算法、Canny边缘检测器算法1.Marr-Hildreth算法详解算法步骤公式Python实现详细解释优缺点2.Canny边缘检测器算法详解算法步骤公式Python实现详细解释优缺点1.Marr-Hildreth算法详解Marr-Hildreth算法是一个......
  • python实现盲反卷积算法
    python实现盲反卷积算法盲反卷积算法算法原理算法实现Python实现详细解释优缺点应用领域盲反卷积算法盲反卷积算法是一种图像复原技术,用于在没有先验知识或仅有有限信息的情况下,估计模糊图像的原始清晰图像和点扩散函数(PSF)。盲反卷积在摄影、医学成......
  • Python——异常捕获,传递及其抛出操作
    01.异常的概念1.程序在运行时,如果python解释器遇到一个错误,会停止程序的执行,并且提示一些错误信息,这就是异常。2.程序停止执行并且提示错误信息这个动作,我们通常称之为:抛出(raise)异常。 程序开发时,很难将所有的特殊情况都处理的面面俱到,通过异常捕获可以针对突发事件做......