gpt4 book ai didi

python - 在系数之间添加乘号(*)

转载 作者:太空狗 更新时间:2023-10-29 18:32:25 25 4
gpt4 key购买 nike

我有一个程序,其中用户输入一个函数,例如sin(x)+1。我正在使用ast尝试通过白名单组件来确定字符串是否“安全”,如this answer中所示。现在,我想分析字符串,在没有系数的情况下在系数之间添加乘号(*)。
例如:
3x>3*x
4(x+5)>4*(x+5)
sin(3x)(4)>sin(3x)*(4)sinis already in globals,others this would bes*i*n*(3x)*(4)
有没有有效的算法来完成这一点?我更喜欢蟒蛇式的解决方案(也就是说,不是复杂的正则表达式,不是因为它们是蟒蛇式的,而是因为我不太了解它们,想要一个我能理解的解决方案。简单的正则表达式可以。)
我非常愿意在一个条件下使用sympy(这对于这类事情来说非常简单):安全。显然,在引擎盖下使用。我目前的(部分)解决方案非常安全。如果有人能用不可信的输入来使sympy更安全,我也欢迎这样做。

最佳答案

regex很容易是用普通的python完成任务的最快、最干净的方法,我甚至会为您解释regex,因为regex是一个非常强大的工具,理解起来很好。
要实现您的目标,请使用以下声明:

import re
# <code goes here, set 'thefunction' variable to be the string you're parsing>
re.sub(r"((?:\d+)|(?:[a-zA-Z]\w*\(\w+\)))((?:[a-zA-Z]\w*)|\()", r"\1*\2", thefunction)

我知道它有点长,也有点复杂,但是一个不同的,简单的解决方案如果没有比这里的regex更黑的东西,它不会立即变得明显。但是,这已经针对您的三个测试用例进行了测试,并且可以根据您的需要进行精确的计算。
简要解释一下这里发生了什么:第一个参数是正则表达式,它与特定的模式匹配。第二个是我们将其替换为的内容,第三个是要替换其中内容的实际字符串。每次我们的regex看到一个匹配,它会删除它并插入替换,使用一些特殊的幕后技巧。
对regex的更深入分析如下:
re.sub:匹配数字或函数调用,后跟变量或括号。
((?:\d+)|(?:[a-zA-Z]\w*\(\w+\)))((?:[a-zA-Z]\w*)|\():第1组。注意:括号分隔一个组,这是一种子正则表达式。捕获组被编入索引以供将来参考;组也可以用修饰符重复(稍后描述)。此组与数字或函数调用匹配。
((?:\d+)|(?:[a-zA-Z]\w*\(\w+\))):非捕获组。在左括号后立即带有 (?:\d+)的任何组都不会为其自身分配索引,但仍然充当模式的“部分”。例如, ?:将匹配“abcbcbc…”等等,但您不能访问“bcbcbcbc”匹配索引。但是,如果没有这个组,写“abc+”将匹配“abcccccc…”
A(?:bc)+:匹配任何数字一次。所有regex都将分别匹配 \d\d"1"的。
"2":与上一个元素匹配一次或多次。在这种情况下,前一个元素是 "3",任意数字。在上一个示例中,“123”上的 "123"将成功匹配“123”作为单个元素。这对我们的regex非常重要,以确保正确注册多位数。
在regex中,它有效地表示 +\d将匹配 \d+|。在这种情况下,它将“一个数字”和“一个函数调用”分开;匹配一个数字或一个函数调用。
or:匹配函数调用。也是一个非捕获组,如 "a|b"
"a":匹配函数调用的第一个字母。因为我们只需要确保第一个字符是字母; "b"在技术上是一个有效的函数名,所以没有对此进行修改。
(?:[a-zA-Z]\w*\(\w+\)):匹配任何字母数字字符或下划线。确保第一个字母后,以下字符可以是字母、数字或下划线,并且仍然作为函数名有效。
(?:\d+):与前一个元素匹配0次或更多次。虽然最初看起来不必要,但星形字符有效地使元素成为可选的。在这种情况下,我们修改的元素是 [a-zA-Z],但函数在技术上不需要任何多个字符; A123是有效的函数名。 \w将与 *匹配,使 \w不必要。在光谱的另一端,第一个字母后面可能有任意数量的字符,这就是为什么我们需要这个修饰符。
理解这一点很重要:这不是另一组。这里的反斜杠的作用类似于普通字符串中的转义符。在regex中,只要在特殊字符(如括号、 A()A前面加上反斜杠,它就像普通字符一样使用它。 [a-zA-Z]匹配函数的实际函数调用部分的左括号。
\w:匹配数字、字母或下划线一次或多次。这样可以确保函数中实际上有一个参数。
\(:like +,但与右括号匹配
*:第2组。匹配变量或左括号。
\(:匹配变量。这与我们的函数名matcher完全相同。但是,请注意,这是一个非捕获组:这很重要,因为OR检查的方式。紧接着的或将把这个组看作一个整体。如果未对其进行分组,“Last object matched”将为 \w+,这将不足以满足我们的需要。它会说:“匹配一个字母后跟多个字母,或者一个字母后跟一个圆括号。”将此元素放入非捕获组中可以控制OR寄存器的内容。
\):或字符。匹配 \(((?:[a-zA-Z]\w*)|\()
(?:[a-zA-Z]\w*):匹配左括号。一旦我们检查了是否有一个左括号,我们就不需要为了我们的regex检查它之外的任何东西。
现在,还记得我们的两组,第一组和第二组吗?这些用于替换字符串, \w*。替换字符串不是真正的regex,但它仍然具有某些特殊字符。在这种情况下, |将插入该号码的组。所以我们的替换字符串是这样说的:“将组1放入(要么是我们的函数调用,要么是我们的数字),然后放入星号(*),然后放入第二个组(要么是变量,要么是括号)。
我想总结一下!

关于python - 在系数之间添加乘号(*),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35929640/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com