【问题标题】:How do I check if a line is a valid function call in python?如何检查一行是否是python中的有效函数调用?
【发布时间】:2018-02-19 16:51:25
【问题描述】:

背景:我目前正在为 ipython 创建一个 line-magic。这种魔法只适用于将函数的返回值分配给变量的行。

我正在寻找一种方法来确保一行是 python 中的有效函数调用+赋值。

例如应接受以下内容:

a = b()
a,b = c(d,e="f")
a = b(c()+c)

以下内容将被拒绝:

a = def fun() # no function call
b(a=2) # no assignment
a = b + c # no function call 
a = b() + c() # top-level on right-hand-side must be function call

如果该行根本不是有效的python,我不在乎它是否通过,因为这将在另一个阶段处理。

【问题讨论】:

  • 你应该写一个解析器。正则表达式对此不够强大。

标签: python regex parsing string-operations


【解决方案1】:

您可以使用 Python 自己的解析器(可通过 ast 模块访问)来直接检查每个语句,以查看它是否是右侧是调用的赋值。

import ast

def is_call_assignment(line):
    try:
        node = ast.parse(line)
    except SyntaxError:
        return False
    if not isinstance(node, ast.Module):
        return False
    if len(node.body) != 1 or not isinstance(node.body[0], ast.Assign):
        return False
    statement = node.body[0]
    return isinstance(statement.value, ast.Call)


test_cases = [
    'a = b()',
    'a,b = c(d,e="f")',
    'a = b(c()+c)',
    'a = def fun()',
    'b(a=2)',
    'a = b + c',
    'a = b() + c()'
]

for line in test_cases:
    print(line)
    print(is_call_assignment(line))
    print("")

结果:

a = b()
True

a,b = c(d,e="f")
True

a = b(c()+c)
True

a = def fun()
False

b(a=2)
False

a = b + c
False

a = b() + c()
False

【讨论】:

  • 这太棒了。我什至不知道你能做到这一点!
【解决方案2】:

我想出的最好的:

  1. 应用这个正则表达式
    [A-z, ]*= *[A-z_]* *\(.*\)
  2. 在第一个“=”处拆分
  3. 确保括号平衡,但如果括号计数在最后一个括号之前达到零,则失败

需要第 3 步,才能使这种情况失败:

a = b() + c() # top-level on right-hand-side must be function call

第 3 步也看起来像这样:

def matched(str):
    count = 0
    for i in str.strip():
        if i == "(":
            count += 1
        elif i == ")":
            count -= 1
        if count < 0 or (count < 1 and i>=len(str)-1):
            return False
    return count == 0

(基于this)

这个解决方案非常丑陋,因为如果顶层没有函数调用,我无法弄清楚如何很好地失败。

一个更好的解决方案可能使用 python 的 AST,但我不知道如何访问它。

猜你喜欢
  • 2015-10-12
  • 2011-04-07
  • 2014-07-05
  • 1970-01-01
  • 2015-04-30
  • 2012-04-16
  • 2020-11-11
  • 2012-06-13
  • 2011-09-08
相关资源
最近更新 更多