由于某种原因,代码无法完全运行

时间:2017-05-26 16:33:32

标签: python sympy

我正在为数学计算器编写代码,并且遇到了问题。当我要求用户输入要派生的函数时,他们输入一个数字,然后输入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()

中收到此错误
Enter f(x): 3x
Traceback (most recent call last):

  File "<ipython-input-48-f4cd19afbde9>", line 1, in <module>
    a=Derivatives()

  File "/Volumes/PROJECTS/M_series.py", line 71, in __init__
    x=sympy.Symbol('x')

  File "/Users/thomastierney/anaconda/lib/python3.5/site-packages/sympy/core/function.py", line 1691, in diff
    return Derivative(f, *symbols, **kwargs)

  File "/Users/thomastierney/anaconda/lib/python3.5/site-packages/sympy/core/function.py", line 1018, in __new__
    expr = sympify(expr)

  File "/Users/thomastierney/anaconda/lib/python3.5/site-packages/sympy/core/sympify.py", line 324, in sympify
    raise SympifyError('could not parse %r' % a, exc)

SympifyError: Sympify of expression 'could not parse '3x'' failed, because of exception being raised:
SyntaxError: invalid syntax (<string>, line 1)

1 个答案:

答案 0 :(得分:2)

一些问题:

  1. 使用func作为字符串的名称具有误导性(Python允许使用一阶函数,因此您可能希望它实际上一个函数);我们改为称之为fn_str

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

  3. 施工

    for i in range(len(mystring)):
        do_something(mystring[i])
    

    更明确地写为

    for ch in mystring:
        do_something(ch)
    
  4. isinstance(func[i], int)无法正常工作,因为func[i]是一个字符的字符串,而不是整数。请改为str.isdecimal()

  5. self.math_symbols未定义。

  6. Python字符串是不可变的;每次执行mystring += ch时,它实际上都会创建一个全新的字符串。因此,在完成后附加到字符串块列表然后"".join()它们会更有效率。

  7. for c in range(48, 57):Python范围不包含end值,即这将产生48,49,50,... 56.这意味着chr(57)即&#34 ; 9&#34;从未进行过测试。

  8. 同样,字符串切片不包含end偏移量,因此func[i:i+1]是一个字符,完全等同于func[i]。你的意思是func[i:i+2]

  9. 此外,3.之类的内容是有效的Python浮点数,但您的代码不会捕获3.x。进行适当的标记化而不是逐个字符的比较可以捕捉到它。

  10. 该课程不是衍生品;你试图将你的程序填入错误标记的课程中。

  11. 清理版本:

    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