python将不同的**KWARG传递给多个函数
通过python文档和stackoverflow,我了解了如何在def函数中使用**kwargs。但是,我有一个案例需要两组**KWARG用于两个子功能。有人能告诉我如何正确地分开**kwargs吗 我的目标是:绘制一组点和插值平滑曲线,python将不同的**KWARG传递给多个函数,python,function,keyword-argument,Python,Function,Keyword Argument,通过python文档和stackoverflow,我了解了如何在def函数中使用**kwargs。但是,我有一个案例需要两组**KWARG用于两个子功能。有人能告诉我如何正确地分开**kwargs吗 我的目标是:绘制一组点和插值平滑曲线, 还有我的简单示例代码: def smoothy(x,y, kind='cubic', order = 3, **kwargs_for_scatter, **kwargs_for_plot): yn_cor = interp1d(x, y, kind=k
还有我的简单示例代码:
def smoothy(x,y, kind='cubic', order = 3, **kwargs_for_scatter, **kwargs_for_plot):
yn_cor = interp1d(x, y, kind=kind, assume_sorted = False)
xn = np.linspace(np.min(x), np.max(x), len(x) * order)
plt.scatter(x,y, **kwargs_for_scatter)
plt.plot(xn, yn_cor(xn), **kwargs_for_plot);
return
谢谢你的帮助。没有这样的机制。有一个建议,即Python3.5和下面的泛化参数解包。Python3.4和以前的版本不支持它。一般来说,您能做的最好的事情是:
def smoothy(x,y, kind='cubic', order = 3, kwargs_for_scatter={}, kwargs_for_plot={}):
yn_cor = interp1d(x, y, kind=kind, assume_sorted = False)
xn = np.linspace(np.min(x), np.max(x), len(x) * order)
plt.scatter(x,y, **kwargs_for_scatter)
plt.plot(xn, yn_cor(xn), **kwargs_for_plot);
return
然后将这些选项作为字典(而不是kwargs)传递到smoothy
smoothy(x, y, 'cubic', 3, {...}, {...})
因为变量名可能会向调用者公开,所以您可能希望将它们重命名为较短的名称(可能是scatter\u options
和plot\u options
)
更新:Python 3.5和3.6现在是主流,它们确实支持基于PEP-448的扩展解包语法
>>> d = {'name': 'joe'}
>>> e = {'age': 20}
>>> { **d, **e }
{'name': 'joe', 'age': 20}
然而,在这个用于多个目的地场景的kwargs中,这并没有多大帮助。即使smoothy()
函数使用统一的kwargs抓包,您也需要确定它们中的哪些用于哪些子函数。最好是一团糟。多个dict
参数,其中一个要传递给每个kwarg-taking子函数,这仍然是最好的方法。使用类获得帮助
我来问这个问题,因为我需要做类似的事情。经过一番思考,似乎课堂教学法会对我有所帮助。我希望这也能推广到其他一些国家
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import interp1d
class KWAs:
def __init__(self, algo):
self.algo = algo
self.kwargs_dict = {
'scatter_params':{},
'plot_params':{}
} # preloading group keys allows plotting when a kwarg group is absent.
def add_kwargs_to_dict(self, group_name, **kwargs):
self.kwargs_dict[group_name] = kwargs
def list_kwargs(self):
print('Listing all kwarg groups:')
for kwargs in self.kwargs_dict:
print('\tkwarg group {}: {}'.format(kwargs, self.kwargs_dict[kwargs]))
print()
def get_kwarg_group(self,group):
print('kwarg group {}: {}'.format(group, self.kwargs_dict[group]))
print()
def smoothy(self, x,y, kind='cubic', order = 3):
yn_cor = interp1d(x, y, kind=kind, assume_sorted = False)
xn = np.linspace(np.min(x), np.max(x), len(x) * order)
plt.scatter(x,y, **self.kwargs_dict['scatter_params'])
plt.plot(xn, yn_cor(xn), **self.kwargs_dict['plot_params'])
plt.show()
kwas = KWAs('LSQ')
N = 20
colors = np.random.rand(N)
area = (20 * np.random.rand(N))**2
kwas.add_kwargs_to_dict('scatter_params', s=area, c=colors, alpha=0.5)
kwas.add_kwargs_to_dict('plot_params', linewidth=2.0, color='r')
kwas.list_kwargs()
kwas.get_kwarg_group('scatter_params')
kwas.get_kwarg_group('plot_params')
x = []; y = []
for i in range(N):
x.append(float(i)*np.pi/float(N))
y.append(np.sin(x[-1]))
kwas.smoothy(x, y)
我不知道您试图用kwargs控制哪些参数,所以我根据matplotlib示例制作了一些。上述方法有效,您可以将无限数量的kwarg组添加到类的kwargs字典中,并添加可以根据需要使用kwargs的其他方法
下面是使用我添加的参数的输出:
另一种更不同的方法
我意识到我参加聚会有点晚了。然而,在处理由其他几个类组成的类时,我偶然发现了一个类似的问题。我希望避免为每个子类(或-函数)传递字典,如果复制组件类的所有参数并在稍后阶段更新所有参数,那将是非常不安全的
我的解决方案当然不是最短的,也不是很好,但我认为它有一定的优雅。我修改了下面的函数smoothy
:
import inspect
def smoothy(x,y, kind='cubic', order = 3, **kwargs):
yn_cor = interp1d(x, y, kind=kind, assume_sorted = False)
xn = np.linspace(np.min(x), np.max(x), len(x) * order)
scatter_args = [k for k, v in inspect.signature(plt.scatter).parameters.items()]
scatter_dict = {k: kwargs.pop(k) for k in dict(kwargs) if k in scatter_args}
plt.scatter(x,y, **scatter_dict)
plot_args = [k for k, v in inspect.signature(plt.plot).parameters.items()]
plot_dict = {k: kwargs.pop(k) for k in dict(kwargs) if k in plot_args}
plt.plot(xn, yn_cor(xn), **plot_dict);
return
解释
首先,使用inspect.signature()
列出第一个函数(scatter)接受的参数(scatter\u args
)。然后从kwargs构造一个新的字典(scatter\u dict
),只提取参数列表中的项目。在这里使用dict(kwargs)
可以确保我们循环使用kwargs的副本,这样我们就可以在不出错的情况下更改原始文件。然后可以将这个新字典传递给函数(scatter),并为下一个函数重复这些步骤
一个陷阱是kwargs中的参数名称可能不会重复,因为它现在是一个单独的dict。因此,对于不控制参数名称的预构建函数,此方法可能会遇到问题
这确实允许我将所述合成类用作父类(或子类)(传递kwargs的剩余部分)。只传递
scatter
和plot
作为正常dict
s?看起来它们是必需的参数。。。然后在函数中使用**散布
或**绘图
。。。你没有对他们做任何其他事情,因为我建议不要再在参数中保留kwargs\u for
。。。(无论如何,@JonClements看起来我们有一个种族条件/同时编辑,但得出了相同的结论!别担心。。。非常好的答案(尽管我有偏见的咳嗽)。。。我只是不确定是这么简单,还是需要更复杂的东西+我写了一篇关于拼写和选项的文章:)