[英]python pass different **kwargs to multiple functions
通过python doc和stackoverflow,我了解了如何在def函数中使用** kwargs。 但是,我有一个案例需要两个子函数使用两组** kwarg。 有人可以告诉我如何正确分离**垃圾吗?
这是我的目标:绘制点集和插值的平滑曲线,
和我朴素的示例代码:
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
感谢帮助。
没有这种机制。 有一个建议书PEP-448 ,据此,Python 3.5及后续版本可以对参数解压缩进行泛化。 Python 3.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_options
和plot_options
)。
更新 :Python 3.5和3.6现在是主流,它们确实支持基于PEP-448的扩展解压缩语法。
>>> d = {'name': 'joe'}
>>> e = {'age': 20}
>>> { **d, **e }
{'name': 'joe', 'age': 20}
但是,在这个kwargs打算用于多个目的地的方案中,这没有太大帮助。 即使smoothy()
函数采用统一的smoothy()
包,您也需要确定其中的哪个子函数用于哪些子函数。 最好是凌乱的。 多个dict
参数(最好传递给每个kwarg子功能)仍然是最好的方法。
我意识到我参加聚会有点晚了。 但是,在处理由其他几个类组成的类时,我偶然发现了一个类似的问题。 我想避免为每个子类(或-function)传递字典,并且复制组件类的所有参数非常不干 ,而且冒着必须在以后更新所有它们的风险。
我的解决方案当然不是最短的,也不是很好,但是我认为它具有一定的优雅。 我在下面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_args
inspect.signature()
。 然后从kwargs构造一个新的字典( scatter_dict
),仅提取也在我们的参数列表中的项。 在这里使用dict(kwargs)
可以确保我们遍历kwargs的副本,以便我们可以更改原始文件而不会出错。 然后可以将此新词典传递给函数(散点图),并为下一个函数重复这些步骤。
一个陷阱是,kwargs中的参数名称不能重复,因为它现在是一个字典。 因此,对于不控制参数名称的预构建函数,此方法可能会遇到问题。
这的确使我可以将所述组合类用作父(或子)类(传递剩余的kwarg)。
我遇到了这个问题,因为我需要做类似的事情。 经过一番思考,似乎课堂教学会对我有所帮助。 我希望这也可以扩展到其他一些人。
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示例中补充了一些参数。 上面的方法行得通,您可以在类的kwargs字典中添加无限数量的kwarg组,并添加可以根据需要使用kwargs的其他方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.