通过签名查询Python函数

时间:2011-01-26 15:43:08

标签: python reflection

记录/修饰Python函数/方法的最佳方法是什么,以便您能够通过签名轻松查询它们(例如参数计数,参数类型和返回类型)?

我正在使用遗传编程包,我想扩展它,以便能够动态替换表达式中的函数,方法是使用等效签名从模块中的所有函数中随机选择替换。

我正在考虑滚动自己的装饰器,所以我可以做类似的事情:

@validate(args=((int, range(1,10), (float, range(1,10)), (bool,)), returns=(int,range(-10,10))
def myfunc(a, b, c):
    result = do_stuff
    return result

然后能够通过执行以下操作来查询类似的函数:

similar_functions = find_functions(like=myfunc)

这条线上是否有任何标准工具或库?

3 个答案:

答案 0 :(得分:2)

您可以使用inspect获取函数的参数列表。这包括默认值,但当然不能提供类型,因为这些定义缺少此信息。

如果您需要类型信息,那么您所展示的装饰者似乎是2.x的最佳解决方案。但我可能会使他们的语法不那么括号:

@validate(a=(int, 1, 10), b=(float, 1, 10), c=bool, returns=(int, -10, 10))
def foo(a, b, c): ...

如果装饰器实际检查函数的arglist并确保它与装饰器的参数匹配,则可能会检测到明显的错误。如果您不打算添加验证代码,则无需修改实际功能。

请注意,您需要对*arg**kwarg进行特殊处理:提供类型信息要困难得多,而且我不知道f1(int, int, int)类似于f2(int, *ints),更不用说f3(int, **kwargs)

答案 1 :(得分:2)

为了与“我们都是成年人”的心态保持一致,为什么需要确保实际遵守指定的类型? 知道函数的签名是什么意思,所以只需用装饰器标记每个函数并将标签存储在字典中。

>>> import collections
>>> tags = collections.defaultdict(set)
>>>
>>> def tag(tag):
...     def decorator(func):
...             tags[tag].add(func)
...             func.tag = tag
...             return func
...     return decorator
...
>>> @tag("foo")
... def a(): pass
...
>>> @tag("foo")
... def b(): pass
...
>>> tags['foo']
{<function b at 0x0000000002BF2448>, <function a at 0x0000000002BD5A48>}

similar是微不足道的:

def similar(func):
    return signatures[func.sig]

答案 2 :(得分:0)

  

通过使用等效签名从模块中的所有函数中随机选择替换,动态替换表达式中的函数。

就这样做。

all_functions_of_some_sig = [
    myfunc, myfunc2, myotherfunc, ... 
]

这并不难。并且它更有可能工作,因为任何过滤或匹配都将由函数的设计者完成。


这可能更简单

def myfunc( a, b, c ):
    return something
myfunc.args= ((int, range(1,10), (float, range(1,10)), (bool,))
myfunc.returns= (int,range(-10,10))

patterns= collections.defaultdict( list )
for f in __all__:
    patterns[f.args,f.returns]= f

这就是你想要的吗?

然后,您需要确保__all__列出所有相关功能。不难做到,并且通常期望包含数千个函数的模块。

相关问题