Python中函数参数的模式匹配

Mor*_*a R 7 python function parameter-passing pattern-matching python-3.x

假设我有一个名为的函数generator,它返回一个在某些预先指定的范围内随机选择的值的4元组.让我们说元组是这样的形式(age, sex, location, marital_status):

age is in range(5, 85)
sex is a member of the set {"m", "f"}
location is a member of the set of all the cities in California
marital_status is a member of {"married", "single", "separated"}
Run Code Online (Sandbox Code Playgroud)

另一方面,假设我已经定义了20个不同的函数,其定义如下:

def p1 (age, sex, location, marital_status)
def p2 (age, sex, location, marital_status)   
.
.
Run Code Online (Sandbox Code Playgroud)

p1应该在哪里接收具有以下形式的值的参数:

`age` must be in the range 20 to 45
`sex` must be male
`location` could be any city in Southern California
`marital_status` could be either single or married
Run Code Online (Sandbox Code Playgroud)

和想象不同的组值p2一路p20.

什么是实用的方法来确定哪组生成的值与哪个函数匹配?

在这种情况下,所有在那里完全一样,但我可以想像情况下,人们可能会在定义略有差异,例如定义p18可能是def p1 (age, location)对的对可能性的范围具体限制agelocation.

PS模式不一定是互斥的,这意味着一组生成的值可能匹配多个函数.

Kas*_*mvd 2

作为 Python 3.X(但不是 2.X)中的 Pythonic 方式,您可以将注释信息(有关函数\xe2\x80\x99s 参数和结果的任意用户定义数据)附加到函数对象。在这里,您可以在装饰器中使用此功能来包装您的函数以检查参数的范围。

\n\n

例如,您可以使用以下范围测试函数:

\n\n
def rangetest(func):\n    def onCall(**kargs):\n        argchecks = func.__annotations__\n\n        if all(val in range(*argchecks.get(arg)) for arg,val in kargs.items()):\n            return func(**kargs)\n        else :\n              print ("invalid arg range")\n    return onCall\n\n\n@rangetest\ndef func(a:(1, 5), b:(4,7), c:(0, 10)):\n    print(a + b + c)\n
Run Code Online (Sandbox Code Playgroud)\n\n

演示:

\n\n
func(a=2, b=6, c=8)\n16\nfunc(a=2, b=6, c=15)\ninvalid arg range\n
Run Code Online (Sandbox Code Playgroud)\n\n

这里有一些要点。首先,由于注释信息位于字典中(python 将其作为字典返回)并且字典没有特定的顺序,因此您需要在函数中使用关键字参数才能获取其相对范围注释信息字典。

\n\n

另外,在这里我只使用了数字范围,但您可以使用一些自定义范围,例如单词列表,例如您在问题中显示的内容。但是在其中all您需要检查其类型,然后根据其类型使用正确的操作:

\n\n
all(kwargs.get(arg) in range(*arg_range) if is instance (arg_range,tuple) else kwargs.get(arg) in arg_range for arg,arg_range in argchecks.items())\n
Run Code Online (Sandbox Code Playgroud)\n