Python 代码赢得';因为某种原因我不能完全跑

Python 代码赢得';因为某种原因我不能完全跑,python,sympy,Python,Sympy,我正在为一个数学计算器编写代码,遇到了一个问题。当我要求用户输入一个要推导的函数时,他们输入一个数字,然后输入x,比如3x,而不是3*x。代码崩溃,因为它无法解析它。为了解决这个问题,我有一个函数来清理它,但由于某些原因它甚至不会运行 class Derivatives: def __init__(self): x=sympy.Symbol('x') self.func=self.clean_func((input("Enter f(x): ")))

我正在为一个数学计算器编写代码,遇到了一个问题。当我要求用户输入一个要推导的函数时,他们输入一个数字,然后输入x,比如3x,而不是3*x。代码崩溃,因为它无法解析它。为了解决这个问题,我有一个函数来清理它,但由于某些原因它甚至不会运行

class Derivatives:
    def __init__(self):
        x=sympy.Symbol('x')
        self.func=self.clean_func((input("Enter f(x): ")))
        print(self.func)
        print(sympy.diff(self.func, x))

    def clean_func(self, func):
        clean_func=""
        print("c")            
        for i in range(len(func)):
            if func[i].isalpha or isinstance(func[i], int) or func[i] in self.math_symbols :
                if func[i]== "^" :
                    clean_func+="**"
                else:
                    clean_func+=func[i]
                for c in range(48, 57) :
                    if func[i:i+1] == (chr(c) + 'x') :
                        clean_func+="*"         #helps with parsing
        return clean_func
我在
a=Derivatives()

输入f(x):3x
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
a=衍生工具()
文件“/Volumes/PROJECTS/M_series.py”,第71行,在__
x=符号('x')
文件“/Users/thomastierney/anaconda/lib/python3.5/site packages/sympy/core/function.py”,第1691行,格式不同
返回导数(f,*符号,**kwargs)
文件“/Users/thomastierney/anaconda/lib/python3.5/site packages/sympy/core/function.py”,第1018行,在新的__
expr=sympify(expr)
sympify中的文件“/Users/thomastierney/anaconda/lib/python3.5/site packages/sympy/core/sympify.py”,第324行
引发SympifyError('无法分析%r'%a,exc)
SympifyError:表达式“的Sympify”无法分析“3x”失败,因为引发了异常:
SyntaxError:无效语法(,第1行)
有几个问题:

  • 使用
    func
    作为字符串的名称是有误导性的(Python允许使用一阶函数,因此您希望它实际上是一个函数);让我们把它叫做
    fn\u str

  • 如果
    clean_func
    工作正常,它将返回一个
    sympy
    -可解析字符串-然后将其传递到
    diff
    ,而不从字符串转换为函数

  • 建筑

    for i in range(len(mystring)):
        do_something(mystring[i])
    
    更清楚地写为

    for ch in mystring:
        do_something(ch)
    
  • isinstance(func[i],int)
    不起作用,因为
    func[i]
    是一个单字符字符串,而不是整数。请尝试使用str.isdecimal()

  • self.math\u符号
    未定义

  • Python字符串是不可变的;每次执行
    mystring+=ch
    时,它实际上会创建一个全新的字符串。因此,在字符串块列表中追加内容,然后在完成后将其添加到
    “”。join()
    会更加有效

  • 用于范围(48,57)中的c
    :Python范围不包括
    end
    值,即这将产生48,49,50。。。56这意味着chr(57)ie“9”从未进行过测试

  • 类似地,字符串片段不包括
    end
    偏移量,因此
    func[i:i+1]
    是一个字符,完全等同于
    func[i]
    。你的意思是
    func[i:i+2]

  • 另外,类似于
    3.
    的代码是一个有效的Python浮点值,但是您的代码将无法捕获
    3.x
    。进行适当的标记化而不是逐个字符的比较将抓住这一点

  • 该类不是衍生产品;您正试图将程序塞入一个标签错误的类中

  • 已清理版本:

    import string
    import sympy
    
    # This could easily be just a function;
    # I made it a class to keep the namespace clean
    class FnStrCleaner:
        # valid characters
        NUMCHARS   = set(string.digits + ".")
        VARCHARS   = set(string.ascii_letters)
        OPCHARS    = set("()+-*/^")
        LEGALCHARS = NUMCHARS | VARCHARS | OPCHARS
    
        @classmethod
        def clean(cls, fn_str):
            # generator expression - skip nonlegal chars
            good_chars = (ch for ch in fn_str if ch in cls.LEGALCHARS)
            out = []
            # simple FSM to process character stream
            prev_num = False   # preceding character was part of a number
            for ch in good_chars:
                if prev_num:
                    if ch in cls.NUMCHARS:
                        out.append(ch)
                        # prev_num = True
                    elif ch in cls.VARCHARS:
                        out.append('*' + ch)
                        prev_num = False
                    else:  # ch in cls.OPCHARS
                        out.append(ch)
                        prev_num = False
                else:
                    if ch in cls.NUMCHARS:
                        out.append(ch)
                        prev_num = True
                    elif ch in cls.VARCHARS:
                        out.append(ch)
                        # prev_num = False
                    else:  # ch in cls.OPCHARS
                        out.append('**' if ch == '^' else ch)
                        # prev_num = False
            return "".join(out)
    
    def get_function(prompt, locals=None):
        fn_str = input(prompt)
        fn_str = FnStrCleaner.clean(fn_str)
        return sympy.sympify(fn_str, locals=locals)
    
    def main():
        x  = sympy.Symbol("x")
        f  = get_function("Enter f(x): ", {'x': x})
        df = sympy.diff(f, x)
        print("f(x) =", f)
        print("f'(x) =", df)
    
    if __name__ == "__main__":
        main()
    
    就像

    Enter f(x): 29x^3 + 12x^2 - 9x + 5
    f(x) = 29*x**3 + 12*x**2 - 9*x + 5
    f'(x) = 87*x**2 + 24*x - 9
    
    有几个问题:

  • 使用
    func
    作为字符串的名称是有误导性的(Python允许使用一阶函数,因此您希望它实际上是一个函数);让我们把它叫做
    fn\u str

  • 如果
    clean_func
    工作正常,它将返回一个
    sympy
    -可解析字符串-然后将其传递到
    diff
    ,而不从字符串转换为函数

  • 建筑

    for i in range(len(mystring)):
        do_something(mystring[i])
    
    更清楚地写为

    for ch in mystring:
        do_something(ch)
    
  • isinstance(func[i],int)
    不起作用,因为
    func[i]
    是一个单字符字符串,而不是整数。请尝试使用str.isdecimal()

  • self.math\u符号
    未定义

  • Python字符串是不可变的;每次执行
    mystring+=ch
    时,它实际上会创建一个全新的字符串。因此,在字符串块列表中追加内容,然后在完成后将其添加到
    “”。join()
    会更加有效

  • 用于范围(48,57)中的c
    :Python范围不包括
    end
    值,即这将产生48,49,50。。。56这意味着chr(57)ie“9”从未进行过测试

  • 类似地,字符串片段不包括
    end
    偏移量,因此
    func[i:i+1]
    是一个字符,完全等同于
    func[i]
    。你的意思是
    func[i:i+2]

  • 另外,类似于
    3.
    的代码是一个有效的Python浮点值,但是您的代码将无法捕获
    3.x
    。进行适当的标记化而不是逐个字符的比较将抓住这一点

  • 该类不是衍生产品;您正试图将程序塞入一个标签错误的类中

  • 已清理版本:

    import string
    import sympy
    
    # This could easily be just a function;
    # I made it a class to keep the namespace clean
    class FnStrCleaner:
        # valid characters
        NUMCHARS   = set(string.digits + ".")
        VARCHARS   = set(string.ascii_letters)
        OPCHARS    = set("()+-*/^")
        LEGALCHARS = NUMCHARS | VARCHARS | OPCHARS
    
        @classmethod
        def clean(cls, fn_str):
            # generator expression - skip nonlegal chars
            good_chars = (ch for ch in fn_str if ch in cls.LEGALCHARS)
            out = []
            # simple FSM to process character stream
            prev_num = False   # preceding character was part of a number
            for ch in good_chars:
                if prev_num:
                    if ch in cls.NUMCHARS:
                        out.append(ch)
                        # prev_num = True
                    elif ch in cls.VARCHARS:
                        out.append('*' + ch)
                        prev_num = False
                    else:  # ch in cls.OPCHARS
                        out.append(ch)
                        prev_num = False
                else:
                    if ch in cls.NUMCHARS:
                        out.append(ch)
                        prev_num = True
                    elif ch in cls.VARCHARS:
                        out.append(ch)
                        # prev_num = False
                    else:  # ch in cls.OPCHARS
                        out.append('**' if ch == '^' else ch)
                        # prev_num = False
            return "".join(out)
    
    def get_function(prompt, locals=None):
        fn_str = input(prompt)
        fn_str = FnStrCleaner.clean(fn_str)
        return sympy.sympify(fn_str, locals=locals)
    
    def main():
        x  = sympy.Symbol("x")
        f  = get_function("Enter f(x): ", {'x': x})
        df = sympy.diff(f, x)
        print("f(x) =", f)
        print("f'(x) =", df)
    
    if __name__ == "__main__":
        main()
    
    就像

    Enter f(x): 29x^3 + 12x^2 - 9x + 5
    f(x) = 29*x**3 + 12*x**2 - 9*x + 5
    f'(x) = 87*x**2 + 24*x - 9
    

    我把你的干净函数放在我的数学课上,因为这是一个有很多子类的类,所以我要清理很多fn_str,然后就是导数。但是,我不认为我能够访问它,因为它超出了我的派生类。我尝试只做数学。clean(fn_str),但我知道它缺少一个语法“fn_str”,所以我很困惑,它作为数学类的一部分应该可以很好地工作,只要(a)它仍然是一个类方法,(b)它可以访问NUMCHARS、VARCHARS、OPCHARS,勒加查尔斯。你能分享你当前的实际代码吗?hugh_bothwell在hotmail.com。。。尽管这看起来很像上面的第10条:没有理由让FnStrCleaner成为你数学课的一部分。为什么不保持原样呢?刚刚给你发了电子邮件,很抱歉搞砸了。所以我把你的干净函数放在我的数学课上,因为这是一个有很多子类的课,所以我会清理很多fn_str,然后就是导数。然而,我不认为我能够访问它,因为它超出了我的派生类。我试图只做数学清理(fn_str),但我知道它缺少一个绘图“fn_str”,所以我很困惑它应该可以作为p