python将不同的** kwargs传递给多个函数

时间:2014-10-23 17:44:58

标签: python function kwargs

从python doc和stackoverflow,我理解如何在我的def函数中使用** kwargs。但是,我有一个案例需要两套** kwargs用于两个子功能。有人能告诉我如何恰当地分离** kwargs吗?

这是我的目标:绘制点集和插值平滑曲线,
和我天真的示例代码:

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

感谢您的帮助。

3 个答案:

答案 0 :(得分:11)

没有这样的机制。有一个提议,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_optionsplot_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的子函数,仍然是最好的方法。

答案 1 :(得分:3)

另一种不同的方法

我知道我参加聚会有点晚了。但是,在处理由其他几个类组成的类时,我偶然发现了一个类似的问题。我想避免为每个子类(或-function)传递字典,并且复制组件类的所有参数非常不利于 dry ,而且冒着必须更新所有子类的风险他们中的一个。

我的解决方案当然不是最短的,也不是很好,但是我认为它具有一定的优雅。我修改了以下函数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

外植

首先,使用scatter_args列出第一个函数(散点图)接受的参数列表(inspect.signature()。然后从kwargs构造一个新的字典(scatter_dict),仅提取也在我们的参数列表中的项。在此处使用dict(kwargs)可确保我们遍历kwargs副本,以便我们可以更改原始副本而不会出错。然后,可以将此新字典传递给函数(散点图),并为下一个函数重复这些步骤。

一个陷阱是,kwargs中的参数名称不能重复,因为它现在是一个字典。因此,对于不控制参数名称的预构建函数,此方法可能会遇到问题。

这确实使我能够将所述组合类用作父(或子)类(传递剩余的kwarg)。

答案 2 :(得分:0)

使用类寻求帮助

我遇到了这个问题,因为我需要做类似的事情。经过一番思考,似乎课堂教学会对我有所帮助。我希望这也可以扩展到其他人。

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的其他方法。

这是使用我添加的参数的输出: enter image description here