检查运算符模块中的参数数量(即add,mul,sub,true_div等...)

时间:2017-05-25 04:53:53

标签: python python-3.x arguments

我试图弄清楚如何使用inspect

import inspect
import operator

inspect.signature(operator.add)

然而我收到以下错误:

Traceback (most recent call last):
  File "D:\ProgramFiles\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 2881, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-82-c98d0a3485c3>", line 1, in <module>
    inspect.signature(operator.__add__)
  File "D:\ProgramFiles\Anaconda3\lib\inspect.py", line 3002, in signature
    return Signature.from_callable(obj, follow_wrapped=follow_wrapped)
  File "D:\ProgramFiles\Anaconda3\lib\inspect.py", line 2752, in from_callable
    follow_wrapper_chains=follow_wrapped)
  File "D:\ProgramFiles\Anaconda3\lib\inspect.py", line 2231, in _signature_from_callable
    skip_bound_arg=skip_bound_arg)
  File "D:\ProgramFiles\Anaconda3\lib\inspect.py", line 2061, in _signature_from_builtin
    raise ValueError("no signature found for builtin {!r}".format(func))
ValueError: no signature found for builtin <built-in function add>

我在这个here上发现了一个类似的线程,但是很久以前这个问题已被标记为重复,并声明他们希望能够为C函数提供一个签名定义,允许该帖子中指定的行为,返回3.4之前。非重复页面为here。但是,尽管如此,从3.6.1开始,看起来有些C函数仍然不是inspectable。然而,这对operator.add()没有多大意义,因为它似乎不应该委托给C函数,即使它确实如此,也是以前签名行为的用例之前提到的python bug报告(所以它让我感到困惑的是为什么我不能将inspect.signature用于operator.add。

我没有寻找args到函数的1:1映射,这根本不适用于我的设置,它不仅包含运算符函数或内置函数,而是任何函数。我也知道我可以将函数包装在另一个函数中,但是在一般情况下,这意味着对于每个具有此问题的函数,我需要为inspect.signature()创建一个个人包装器才能工作。我想知道我上面描述的内容是否可行/最小的解决方法(比如一个通用的包装器,其中包装器的签名将匹配它在参数数量方面包含的函数的签名),如果没有,为什么不呢。

2 个答案:

答案 0 :(得分:2)

  

然而,这对operator.add()没有多大意义,因为它似乎不应该委托给C函数

Well, it does.

看起来current dev branch已将_operator模块更改为使用Argument Clinic而不是3.6及更早版本中基于宏的实现,因此inspect.signature可能适用于3.7。然而,在那之前,你很少有内省。

答案 1 :(得分:0)

我对此感到有些惭愧。但等待3.7不是一种选择。它很好用。当然这是一个野蛮的黑客。

import re

def argnum(op):
  try: 
    op()
  except TypeError as e:
    msg = e.args[0]
    if 'argument' in msg:
      match = re.search(R'(\d+)(?!\sgiven)', e.args[0])
      if match: return int(match.group(1))
      elif 'one' in msg: return 1
    raise e
  else:
    return 0