0

假设我正在编写一个简单的解析器。它有一个调度程序,根据输入表达式的类型调用相应的解析函数。

def dispatcher(expression):
    m = pattern1.match(expression):
    if m is not None:
        handle_type1(expression, m)
    # ... other types

我的问题是,有没有将匹配和检查结合起来None?我的意思是,类似于以下 C 代码:

void dispatcher(char *expression)
{
    if ((m = pattern1.match(expression)) != NULL) {
        // ... handle expression type 1
    }
    else if ((m = pattern2.match(expression)) != NULL) {
        // ... handle expression type 2
    }
    // ... other cases
}

谢谢!

4

4 回答 4

5

这实际上并不是将模式匹配与无检查相结合,而是关于您是否可以分配给一个变量并在一个表达式中评估该分配的结果,因为 pattern.match() 调用可以是任何返回值的函数。

一般来说,答案是否定的,因为在 Python 中赋值是一个语句,而不是 C 中的表达式。

在这种情况下,我可以看到的唯一区别是您为自己节省了一个额外的回车,这不是那么有用。assign-and-compare 习惯用法在循环中更有用,但在 Python 中,您只需要在两行中执行(必要时使用 break)。

于 2012-10-29T13:19:17.357 回答
3

你不觉得你的类似 C 的例子有点重复吗?如果你发现你一遍又一遍地重复代码,那么考虑用循环替换它。这样的事情避免了重复匹配和测试:

def dispatcher(expression):
    for pattern, action in [
        (pattern1, handle_type1),
        (pattern2, handle_type2),
        ]:
        m = pattern.match(expression):
        if m is not None:
           action(expression, m)
           break

您还可以通过各种方式将模式和处理程序列表拉出循环,例如,如果处理程序是同一类的所有方法,您可以定义一个装饰器以使用处理程序旁边定义的模式自动构建列表。

@patternhandler('some regex')
def handle_type1(expression, match):
    ...
于 2012-10-29T13:32:14.333 回答
2

你能做的最好的,并且有一些争论是否更好,就是创建一个类来完成这项工作。然后该类可以保持状态,例如匹配的最后一个模式:

class Matcher(object):
    def __init__(self):
        self.m = None

    def match(self, pattern, text):
        self.m = re.match(pattern, text)
        return self.m


def dispatcher(expression):
    matcher = Matcher()
    if matcher.match(pattern1, expression):
        handle_type1(expression, matcher.m)
    if matcher.match(pattern2, expression):
        handle_type2(expression, matcher.m)
于 2012-10-29T13:31:04.750 回答
1

如今(从 Python 3.8 开始)“海象运算符”:=实现了赋值表达式,允许更简单的公式:

if (m := pattern1.match(expression) is not None:

这完全按照您想要的方式结合了评估和分配。

于 2021-08-18T06:48:05.257 回答