当我尝试在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,但这会产生相同的错误。 我能做错什么?
答案 0 :(得分:2)
你应该将你的论点翻转为get_mu(df, *rel_change)
。不要忘记翻转函数调用:get_mu(df, g)
。可选的位置参数(通常称为参数的传统名称的星形参数,* args)需要在关键字参数之后。
有关更多详细信息,我强烈推荐Brett Slatkin撰写的“有效的Python:编写更好的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:“使用仅关键字参数强制清晰度”)。
要记住的事情
答案 1 :(得分:2)
您已经定义了一个具有可变数量的位置参数NotificationCenter.default.addObserver(
self,
selector: #selector(self.didHideEditMenu),
name: NSNotification.Name.UIMenuControllerDidHideMenu,
object: nil)
NotificationCenter.default.addObserver(
self,
selector: #selector(self.willHideEditMenu),
name: NSNotification.Name.UIMenuControllerWillHideMenu,
object: nil)
的函数,该函数只能跟随关键字参数。在这种情况下,您必须按名称传递*rel_change
:
df
或重新定义mu = get_mu(g, df=df)
,以便在get_mu()
之前显示df
。