如何为Python函数参数提供额外的装饰/元数据?

8 投票
4 回答
3360 浏览
提问于 2025-04-16 03:32

我们正在考虑使用Python(具体是IronPython,不过我觉得这不是重点)来为另一个应用程序提供一种“宏”支持,这个应用程序控制着一台设备。

我们想用Python写一些比较简单的函数,这些函数会接收一些参数,比如时间、温度和位置。不同的函数会接收不同的参数,而主要的应用程序会有一个用户界面(类似属性网格),让用户可以为Python函数的参数提供值。

举个例子,function1可能需要一个时间和一个温度,而function2可能需要一个位置和几个时间。

我们希望能够根据Python代码动态构建用户界面。比较简单的事情是找到模块中的函数列表,并使用inspect.getargspec来获取每个函数的参数列表。

不过,仅仅有参数名称的列表是不够的——理想情况下,我们希望能包含一些关于每个参数的更多信息,比如它的“类型”(高层次的类型,比如时间、温度等,而不是编程语言中的类型),还有可能的“友好名称”或描述。

所以,问题是,有什么好的“Pythonic”方式来为函数添加这种信息。

我想到的两种可能性是:

  • 使用严格的命名约定来命名参数,然后根据它们的名称推断一些信息(通过getargspec获取名称)

  • 发明我们自己的文档字符串元语言(可能只是简单的CSV)并用文档字符串来存储我们的元数据。

因为Python在大型应用程序中构建脚本方面似乎很受欢迎,我想这个问题应该有一些常见的解决方案和约定,但我还没能找到它们。

4 个回答

1

用“python风格”的方法来做这件事,就是使用函数注解

def DoSomething(critical_temp: "temperature", time: "time")
    pass
4

我会使用某种装饰器:

class TypeProtector(object):
    def __init__(self, fun, types):
        self.fun, self.types = fun, types
    def __call__(self, *args, **kwargs)
        # validate args with self.types
        pass
        # run function
        return fun(*args, **kwargs)

def types(*args):
    def decorator(fun):
        # validate args count with fun parameters count
        pass
        # return covered function
        return TypeProtector(fun, args)
    return decorator

@types(Time, Temperature)
def myfunction(foo, bar):
    pass

myfunction('21:21', '32C')
print myfunction.types
7

装饰器是一种很好的方式,可以给函数添加一些额外的信息。你可以创建一个装饰器,它接受一个类型列表,然后把这些类型添加到一个叫做 .params 的属性里,或者其他类似的地方:

def takes(*args):
    def _takes(fcn):
        fcn.params = args
        return fcn
    return _takes

@takes("time", "temp", "time")
def do_stuff(start_time, average_temp, stop_time):
    pass

撰写回答