【问题标题】:Missing 1 Required Keyword-Only Argument缺少 1 个必需的仅关键字参数
【发布时间】:2018-07-26 15:51:10
【问题描述】:

当我尝试在 Python 3.6 中输入数据框作为函数参数时,我收到以下函数的错误“缺少 1 个必需的仅关键字参数”,其中 df 是数据框,rel_change 是数组:

def get_mu(*rel_change, df):

    row_count = len(df.index)
    print("mu count")
    print(row_count)
    mu_sum = 0
    for i in range (0, len(rel_change)):
        mu_sum += rel_change[i]
    mu = (mu_sum) / row_count
    return mu

然后我像访问它

mu = get_mu(g, df) 

这给出了错误。

我还尝试在另一个仅计算 row_count 的函数中编写数据帧访问,并将其传递给 mu,但这会产生相同的错误。 我可能做错了什么?

【问题讨论】:

  • 尝试反转你的函数参数,然后你的函数调用。 def get_mu(df, *rel_changes).... 和 mu = get_mu(df, g)
  • *args 后面的参数是关键字参数,必须按名称传递 mu = get_mu(g, df=df)

标签: python pandas csv dataframe keyword


【解决方案1】:

您已经定义了一个带有可变数量位置参数的函数*rel_change,它后面只能跟关键字参数。在这种情况下,您必须按名称传递 df,如下所示:

mu = get_mu(g, df=df)

或者重新定义get_mu(),使df出现在*rel_change之前。

【讨论】:

    【解决方案2】:

    你应该把你的论点改成get_mu(df, *rel_change)。不要忘记翻转函数调用:get_mu(df, g)。可选的位置参数(通常称为星形参数,参考参数的常规名称 *args)需要放在关键字参数之后。

    要了解更多细节,我强烈推荐 Brett Slatkin 的《Effective Python: 59 Specific Ways to Write Better Python》一书。以下是休息后关于该主题的摘录:


    第 18 项:使用可变位置参数减少视觉噪音

    接受可选的位置参数(通常称为星形参数,参考参数的常规名称 *args)可以使函数调用更清晰并消除视觉噪音。

    例如,假设您想记录一些调试信息。使用固定数量的参数,您将需要一个接收消息和值列表的函数。

    def log(message, values):
        if not values:
            print(message)
        else:
            values_str = ', '.join(str(x) for x in values)
            print('%s: %s' % (message, values_str))
    
    log('My numbers are', [1, 2])
    log('Hi there', [])
    
    >>>
    My numbers are: 1, 2
    

    你好 当您没有要记录的值时,必须传递一个空列表既麻烦又嘈杂。最好完全省略第二个参数。您可以在 Python 中通过在最后一个位置参数名称前加上 * 来执行此操作。日志消息的第一个参数是必需的,而任何数量的后续位置参数都是可选的。函数体不需要改变,只有调用者做。

    def log(message, *values):  # The only difference
        if not values:
            print(message)
        else:
            values_str = ', '.join(str(x) for x in values)
            print('%s: %s' % (message, values_str))
    
    log('My numbers are', 1, 2)
    log('Hi there')  # Much better
    
    >>>
    My numbers are: 1, 2
    
    Hi there
    

    如果你已经有一个列表并且想要调用一个变量参数函数,比如 log,你可以使用 * 操作符来做到这一点。这指示 Python 将序列中的项目作为位置参数传递。

    favorites = [7, 33, 99]
    log('Favorite colors', *favorites)
    
    >>>
    Favorite colors: 7, 33, 99
    

    接受可变数量的位置参数有两个问题。

    第一个问题是变量参数在传递给你的函数之前总是变成一个元组。这意味着如果您的函数的调用者在生成器上使用 * 运算符,它将被迭代直到它用尽。生成的元组将包含生成器中的每个值,这可能会消耗大量内存并导致程序崩溃。

    def my_generator():
        for i in range(10):
            yield i
    
    def my_func(*args):
        print(args)
    
    it = my_generator()
    my_func(*it)
    
    >>>
    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
    

    接受 *args 的函数最适合您知道参数列表中的输入数量相当少的情况。它非常适合将许多文字或变量名一起传递的函数调用。主要是为了程序员的方便和代码的可读性。

    *args 的第二个问题是,如果不迁移每个调用者,将来就无法向函数添加新的位置参数。如果您尝试在参数列表的前面添加位置参数,如果不更新现有调用者,它们将会巧妙地中断。

    def log(sequence, message, *values):
        if not values:
            print('%s: %s' % (sequence, message))
        else:
            values_str = ', '.join(str(x) for x in values)
            print('%s: %s: %s' % (sequence, message, values_str))
    
    log(1, 'Favorites', 7, 33)      # New usage is OK
    log('Favorite numbers', 7, 33)  # Old usage breaks
    
    >>>
    1: Favorites: 7, 33
    Favorite numbers: 7: 33
    

    这里的问题是第二次调用 log 使用 7 作为消息参数,因为没有给出序列参数。像这样的错误很难追踪,因为代码仍然可以运行而不会引发任何异常。为了完全避免这种可能性,当你想扩展接受 *args 的函数时,你应该使用仅关键字参数(参见第 21 条:“使用仅关键字参数强制清晰”)。

    要记住的事情

    • 函数可以通过在 def 语句中使用 *args 来接受可变数量的位置参数。
    • 您可以将序列中的项目用作带有 * 运算符的函数的位置参数。
    • 将 * 运算符与生成器一起使用可能会导致程序内存不足并崩溃。
    • 向接受 *args 的函数添加新的位置参数可能会引入难以发现的错误。

    【讨论】:

      猜你喜欢
      • 2018-09-23
      • 1970-01-01
      • 2022-08-19
      • 2022-11-17
      • 2022-10-30
      • 2021-06-20
      • 2022-10-06
      • 2022-10-09
      • 2020-06-03
      相关资源
      最近更新 更多