如何验证传递给函数的嵌套元组的长度?

How to validate the length of nested tuple passed to a function?

我正在构建一个接受元组列表的函数。例如:

my_list = [
     ("str1", 1, 11),
     ("str2", 2, 22), 
     ("str3", 3, 33),
     ("str4", 4, 44)
] 

我想创建一个定义为只接受每个嵌套元素大小为“3”的参数的函数。我如何定义我的函数以仅接受我想要的嵌套长度的列表?

这是我想要实现的示例代码片段(我知道它在语法上不正确):

def newattr_ratio(data, *(name,idx,idy)):

    for name,idx,idy in *(name,idx,idy):
        data[name]= data[data.columns[idx]]/data[data[columns[idy]]]

如何创建具有此类参数定义的函数?

让函数接受元组列表作为参数

def newattr_ratio(data, myListOfTuples):
    for myTuple in myListOfTuples:
        data[myTuple[0]]= data[data.columns[myTuple[1]]/data[data[columns[myTuple[2]]]

您不能在函数参数声明期间对其进行限制。然而,您可以创建自定义装饰器来检查嵌套元组的长度,如:

from functools import wraps

def check_params(nestedsize=None):
    def _check_params(func):
        def _decorator(data, *args ):
            if nestedsize and all(len(arg)==nestedsize for arg in args):
                return func(data, *args)
            else:
                raise Exception("Invalid args passed with the function call")
        return wraps(func)(_decorator)
    return _check_params

上面的装饰器采用可选参数 nestedsize 来检查嵌套元组的大小。

现在,为了将列表的解压缩版本传递给您的函数,您的函数定义应该是:

@check_params(nestedsize=3)    # <-- added decorator here, with nested size as "3"
def newattr_ratio(data, *args):  # <-- note the asterisk sign here
    for name, idx, idy in args:
        print("{} - {} - {}".format(name, idx, idy))

样本运行:

# Correct input
>>> my_list = [("a", 1, 11), ("b", 2, 22), ("c", 3, 33)]

#                     v asterisk again to unpack the list
>>> newattr_ratio([], *my_list)
a - 1 - 11
b - 2 - 22
c - 3 - 33

# Incorrect input, raising custom exception
>>> my_list = [("a", 1, 11, "wrong_data"), ("b", 2, 22), ("c", 3, 33)]

>>> newattr_ratio([], *my_list)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in _decorator
Exception: Invalid args passed with the function call

如果您不想解压列表并按原样传递它,那么您的函数应该是:

@check_params(nestedsize=3) 
def newattr_ratio(data, args):  # <-- No asterisk here
    for name, idx, idy in args:
        print("{} - {} - {}".format(name, idx, idy))
        # ... whatever your logic is

样例运行 (结果同上,只是函数调用不同):

# correct input
>>> my_list = [("a", 1, 11), ("b", 2, 22), ("c", 3, 33)]
>>> newattr_ratio([], my_list)   # <-- No asterisk here
a - 1 - 11
b - 2 - 22
c - 3 - 33

# Incorrect input, raising custom exception
>>> my_list = [("a", 1, 11, "wrong_data"), ("b", 2, 22), ("c", 3, 33)]

>>> newattr_ratio([], my_list)   # <-- No asterisk here
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in _decorator
Exception: Invalid args passed with the function call

但是,如果您不使用装饰器,您的 for 循环无论如何都会引发异常 ValueError: too many values to unpack。因此,如果没有自定义异常,你可以跳过装饰器

例如:

#                               v extra value here
>>> my_list = [("a", 1, 11, "wrong_data"), ("b", 2, 22), ("c", 3, 33)]

>>> newattr_ratio([], my_list)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in newattr_ratio
ValueError: too many values to unpack

你说的有点不对。处理可变数量参数的格式是"def newattr_ratio(data, *t_uple)"。 “*t_uple”表示它将是可变数量的参数。示例如下:

def add (*arg):
    sum = 0
    for t_uple in arg:
        for x in t_uple:
            sum = sum +x
    return sum

if __name__ == '__main__':
    arg_1 = (1, 2, 3)
    arg_2 = (5, 6, 7)
sum = add(arg_1,arg_2)
print(sum)