Python matplotlib.pyplot.plot的包装函数

Python matplotlib.pyplot.plot的包装函数,python,python-decorators,Python,Python Decorators,我是Python的新手,但对许多其他语言都很有经验!我正在编写一个Python脚本来处理科学测量数据 我最终得到了许多类函数,每个类函数都调用matplotlib.pyplot.plot。我在下面举了一个简单的例子: def plot_measurement(self, x, x_label, y, y_label, plot_label = "", format = "-b", line_width = 1, latex_mode = False): if (plot_label ==

我是Python的新手,但对许多其他语言都很有经验!我正在编写一个Python脚本来处理科学测量数据

我最终得到了许多类函数,每个类函数都调用matplotlib.pyplot.plot。我在下面举了一个简单的例子:

def plot_measurement(self, x, x_label, y, y_label, plot_label = "", format = "-b", line_width = 1, latex_mode = False):
    if (plot_label == ""):
        plot_label = self.identifier

    if (latex_mode):
        matplotlib.rc("text", usetex = True)
        matplotlib.rc("font", family = "serif")

    matplotlib.pyplot.plot(x, y, format, linewidth = line_width, label = plot_label)
    matplotlib.pyplot.xlabel(x_label)
    matplotlib.pyplot.ylabel(y_label)
我希望能够将所有matplotlib.pyplot.plot参数添加到我的新函数中,这样我就可以将它们输入matplotlib.pyplot.plot中,但不希望通过将它们添加到函数声明中来手动执行此操作,您可以从我在某些情况下已经完成的代码片段中看到。关键是每个新函数都有自己的一组参数,这些参数需要与matplotlib.pyplot.plot的参数区别开来

通过一点在线搜索,我发现了Python装饰器,但是我还没有找到一个在这个例子中对我有帮助的好例子。我相信在Python中有一种简单的方法可以做到这一点


如果有人能在这方面帮助我,我将不胜感激。

要扩展@Dr.V的评论,您可以传递一个参数字典,以使用所有位置参数绘制度量,第二个字典包含所有可选参数,以使事情更简单。传统上,这些被称为args和kwargs关键字args。使用*as in*args展开列表,并将每个列表元素作为参数放入函数中;类似地,**展开一个字典,并将每个字典键值对放入函数中,该函数便于关键字参数使用

# also this is standard because it's very convenient
import matplotlib.pyplot as plt

## Examples of how args and kwargs are formatted 

# all required arguments go in a list in order
args = [x,y,format]

# all non-required (keyword) arguments go in a dictionary
kwargs = {
     line_width: 1,
     label: plot_label
     }


def plot_measurement(self,args,kwargs,plot_label,x_label,y_label,latex_mode = False):
    # here all of the args and keyword args are passed together
    # whereas all arguments used directly by plot_measurement are not passed together
    # though they could be for cleanliness

    if (plot_label == ""):
        plot_label = self.identifier

    if (latex_mode):
        matplotlib.rc("text", usetex = True)
        matplotlib.rc("font", family = "serif")

    plt.plot(*args, **kwargs)
    plt.xlabel(x_label)
    plt.ylabel(y_label)
可以在函数签名中使用args和kwargs,并将参数传递给plot函数。这里有一个解释它们是如何工作的,所以我不想在这里重复

实际上,args和kwargs允许您传递数量可变的参数。对于kwargs,它会将传递给字典中函数的任何“额外”关键字参数打包。然后可以将字典传递到接收函数中,并使用**kwargs解包

对于您的功能:

def plot_measurement(x_label, y_label, *args, latex_mode = False, **kwargs):
    # Keyword arguments can be accessed as a normal dictionary
    if (kwargs["label"] == ""):
        kwargs["label"] = self.identifier

    if (latex_mode):
        matplotlib.rc("text", usetex = True)
        matplotlib.rc("font", family = "serif")

    matplotlib.pyplot.plot(*args, **kwargs)
    matplotlib.pyplot.xlabel(x_label)
    matplotlib.pyplot.ylabel(y_label)
使用函数参数调用它,并添加绘图所需的任何额外参数:

args和kwargs将“吸收”传递给函数的任何额外参数。要使用关键字参数,请将其放在函数签名中的所有位置参数之后,函数签名现在包括*args

完整工作示例:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt

def plot_measurement(x_label, y_label, *args, latex_mode = False, **kwargs):
    if (kwargs["label"] == ""):
        kwargs["label"] = self.identifier

    if (latex_mode):
        matplotlib.rc("text", usetex = True)
        matplotlib.rc("font", family = "serif")

    plt.plot(*args, **kwargs)
    plt.xlabel(x_label)
    plt.ylabel(y_label)
    plt.show()

x = np.arange(0, 20)
x = np.reshape(x, (4, 5))
y = np.arange(5, 25)
y = np.reshape(y, (4, 5))

plot_measurement("x axis label", "y axis label", x, y, latex_mode = False, color = "red", label = "plot label")
产生:

对于子孙后代,此响应中发布的代码不起作用,是对@Derek和@Erik的一个小测试用例

我看不到如何把格式化的代码放在评论中,所以我把它贴在这里。请原谅我的罪

def plot_measurement(self, latex_mode = False, *args, **kwargs):
    print("\nlen(args) = {0}, args = {1}".format(len(args), args))
    print("\nlen(kwargs) = {0}, kwargs = {1}\n".format(len(kwargs), kwargs))

    if (latex_mode):
        matplotlib.rc("text", usetex = True)
        matplotlib.rc("font", family = "serif")

    matplotlib.pyplot.plot(*args, **kwargs)
使用以下咒语呼叫

test_measurement1.plot_measurement(test_measurement1.data[6], test_measurement1.data[15])
数据[6]和数据[15]都是numpy.array并连接在一起。输出如下:

len(args) = 1, args = (array([-8.21022986e-06, -8.19599736e-06, -8.16865495e-06, ...,
       -7.70015886e-06, -7.70425522e-06, -7.71744717e-06]),)

len(kwargs) = 0, kwargs = {}
此外,行上的代码错误

if (latex_mode):
给出错误

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

不是关于装饰器,而是变量参数列表?我建议使用关键字参数,如以下所述:感谢您的评论,V博士。我已经找到了该页面,但我不清楚如何将新参数与要传递到matplotlib.pyplot.plot的参数分开。如果您能提供一个如何在代码段中更改函数声明的示例,那将非常棒。谢谢您的评论Erik。这很有帮助。我一直在努力让它发挥作用,但还没有成功。为什么不在函数声明中包含*args呢?我想传递到matplotlib.pyplot.plot*args中的两个numpy.array,但请注意它们是连接在一起的。有什么想法吗?抱歉我错过了那个情节需要位置参数。我将用一个工作示例更新我的答案谢谢你的评论。看起来使用args和kwargs是一个不错的选择。然而,我现在没有太多的运气让它工作。我正在尝试调试/生成一个测试用例,并将向您报告。是否需要将*args放在命名参数关键字参数latex\u mode之前?似乎修复了错误,代码现在可以运行了,但不确定为什么。*arg是位置参数,因此您的关键字参数模式需要像往常一样跟踪所有位置参数。我已经更新了我的答案,展示了如何使用它。谢谢你的帮助Erik。现在,它可以按预期工作。我确实觉得奇怪的是,位置参数不能放在关键字参数之间,因为这样做时,位置参数的顺序仍然定义得很好。
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()