Python 使用递归识别有效正则表达式

Python 使用递归识别有效正则表达式,python,regex,recursion,Python,Regex,Recursion,我一直在开发一个程序,它有一个函数,它接受如下字符串:((1.(0.2)2).0),如果它是正则表达式,则返回True。以下是迄今为止的mmy代码: def is_regex(s): #Takes a string 's' and produces True if it is a valid regular expression #But False otherwise ex = '( + 3* + | + 6* + )' leaves = ['1', '2',

我一直在开发一个程序,它有一个函数,它接受如下字符串:
((1.(0.2)2).0)
,如果它是正则表达式,则返回
True
。以下是迄今为止的mmy代码:

def is_regex(s):
    #Takes a string 's' and produces True if it is a valid regular expression
    #But False otherwise
    ex = '( + 3* + | + 6* + )'
    leaves = ['1', '2', '0', '1*', '2*', '0*']
    internal_nodes = ['|', '.']
    stripped_string = s.strip('()')

    if len(s.strip('()')) == 1:
        if '0' in s.strip('()') or '1' in s.strip('()') or '2' in s.strip('()')  or 'e' in s.strip('()'):
        return True
    elif len(s.strip('()')) == 0:
        return True
    elif stripped_string in leaves[3:6]:
        return True 
    elif len(stripped_string) == 3:
        if stripped_string[0] in leaves and stripped_string[2] in leaves:
            if stripped_string[1] in internal_nodes:
                return True 
    elif '.' in s and len(stripped_string) > 3:
        dot_position = s.rfind('.')
        if s.rfind('.') > s.rfind(')', 0, len(s)-1): #if '.' is only surrounded by one set of () then it is the root of the tree
            is_regex(s[dot_position +1])
这里的想法是我想找到树的根,检查它的两个子项是否有效正则表达式,如果是,我在递归上移动,直到到达叶子,如果它通过所有测试,直到到达叶子,那么整个正则表达式都是
真的

最后一行是正则表达式(s[dot\u position+1])我没有得到任何返回,即使我知道
s[dot\u position+1]
返回
0
,所以应该没有问题。在这一行中,我正在检查
的右子级,即
0


编辑:另一个问题:我需要测试左边的孩子是否也是真的。我该怎么做?我不需要将这两个都传递到
is_regex
?或者我应该检查左右两个是否都为真,然后继续?这让人困惑

这可能是目前最常见的递归错误。如果您不
返回递归调用的结果,Python不会为您返回该结果-它会正常运行函数。因为后面没有其他内容,所以它会从末尾掉下来而不返回—Python的规则意味着它将隐式地
返回None
的结果是\u regex(s[dot\u position+1])
被忽略,除非您显式返回它(或者以其他方式使用它)


通过此函数,在其他两个路径中也存在类似的错误:

if len(s.strip('()')) == 1:
    if '0' in s.strip('()') or '1' in s.strip('()') or '2' in s.strip('()')  or 'e' in s.strip('()'):
    return True

elif len(stripped_string) == 3:
    if stripped_string[0] in leaves and stripped_string[2] in leaves:
        if stripped_string[1] in internal_nodes:
            return True 
在这两种情况下,如果外部if触发,但内部if失败,则最终将不返回任何结果。这并不是一个严重的问题,因为调用代码时,
None
仍然会测试false
if is\u regex(not\u a\u regex)
——但是为了一致性和明确处理这些情况(而不是从根本上忘记它们并让它正常工作),您可能希望返回
false
。最简单的方法是只返回布尔表达式,而不是测试它们:

if len(s.strip('()')) == 1:
    return '0' in s.strip('()') or '1' in s.strip('()') or '2' in s.strip('()')  or 'e' in s.strip('()')

elif len(stripped_string) == 3:
    return stripped_string[0] in leaves and stripped_string[2] in leaves and stripped_string[1] in internal_nodes

为了测试左边的子对象,您确实必须递归到这两个对象中——单独地,注意(将它们传递到同一个递归调用中可能是可行的,但不太可能工作)。我会这样做:

dot_position = s.rfind('.')
if s.rfind('.') > s.rfind(')', 0, len(s)-1): #if '.' is only surrounded by one set of () then it is the root of the tree
    left_child =  s[dot_position - 1]
    right child = s[dot_position + 1]
    return is_regex(left_child) and is_regex(right_child)

在涉及树结构的任何算法中,这是一种非常常见的模式:测试当前节点中的值,然后依次递归调用每个子节点上的相同例程来测试其所有子树;返回一个依赖于所有递归调用结果的结果。维基百科称这是一个错误

好的,我刚刚在最后一行添加了一个
return
语句,为什么它能工作呢?我明白了,谢谢你的洞察力。你有没有办法帮我回答第二个问题?在我检查了左右两个孩子之后,如果他们都是树,我将如何递归到每个孩子身上?这就像同时递归两次哇,谢谢,答案似乎很简单。我很高兴这一困境实际上被记录在案。我知道我需要一种方法来确定两个孩子是否都有效,再次感谢,干杯!