简体   繁体   English

包装 function 用于 matplotlib.pyplot.plot

[英]Wrapper function for matplotlib.pyplot.plot

I'm a relative new comer to Python (but am experienced in many other languages.) and am writing a Python script to process scientific measurement data.我是 Python 的相对新手(但在许多其他语言方面经验丰富。)并且正在编写 Python 脚本来处理科学测量数据。

I've ended up with a number of class functions that each call matplotlib.pyplot.plot().我最终得到了许多 class 函数,每个函数都调用 matplotlib.pyplot.plot()。 I include a simple example below:我在下面包括一个简单的例子:

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)

I would like to be able to add all of the matplotlib.pyplot.plot() parameters to my new functions so that I may feed them into matplotlib.pyplot.plot() but don't wish to do so manually (by adding them to the function declaration), which you'll see from that code snippet that I have already done so in some cases.我希望能够将所有 matplotlib.pyplot.plot() 参数添加到我的新函数中,以便我可以将它们输入 matplotlib.pyplot.plot() 但不希望手动这样做(通过添加它们到 function 声明),您将从该代码片段中看到我在某些情况下已经这样做了。 The crux is that each new function has it's own set of parameters that somehow need to be distinguished from the parameters to matplotlib.pyplot.plot().关键是每个新的 function 都有自己的一组参数,这些参数需要以某种方式与 matplotlib.pyplot.plot() 的参数区分开来。

A little bit of searching online led me to discovering Python decorators but I have not been able to find a good example that will help me in this instance.在网上进行了一些搜索后,我发现了 Python 装饰器,但在这种情况下我找不到一个可以帮助我的好例子。 I'm convinced there is an easy way to do this in Python.我确信在 Python 中有一种简单的方法可以做到这一点。

If someone could please help me with this I would be most grateful.如果有人可以帮助我,我将不胜感激。

You can use args and kwargs in your function signature and pass through arguments to the plot() function.您可以在 function 签名中使用argskwargs并通过 arguments 传递给plot() function。 There are a lot of excellent explanations explaining how they work, so I won't try to repeat it all here.很多很好的解释来解释它们是如何工作的,所以我不会在这里重复一遍。

Essentially args and kwargs allow you to pass a variable number of arguments.本质上argskwargs允许您传递可变数量的 arguments。 In the case of kwargs it packs up any 'extra' keyword arguments you pass to the function in a dictionary.kwargs的情况下,它会打包任何“额外”关键字 arguments 您传递给字典中的 function。 The dictionary can then be passed inside the receiving function and unpacked with **kwargs然后可以在接收 function 内部传递字典并使用**kwargs解包

For your function:对于您的 function:

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)

Call it using the function arguments and adding any extra arguments you need for plot() :使用 function arguments 调用它,并为plot()添加任何额外的 arguments :

plot_measurement("x_label", "y_label", x, y, latex_mode = False, linewidth = 1, label = "plot_label")

args and kwargs will 'soak up' any extra arguments you pass to your function. argskwargs将“吸收”您传递给 function 的任何额外 arguments。 To use your keyword argument, place it after all the positional arguments in the function signature - which now includes *args .要使用您的关键字参数,请将其放在 function 签名中的所有位置 arguments 之后 - 现在包括*args

Full working example:完整的工作示例:

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")

Produces:生产: 在此处输入图像描述

To expand upon @Dr.扩展@Dr。 V 's comment, you can pass a single dictionary of parameters to plot_measurement with all positional arguments and a second with all optional arguments to keep things simpler. V 的评论,您可以将单个参数字典传递给plot_measurement ,其中所有位置为 arguments,第二个参数为所有可选 arguments,以使事情更简单。 Traditionally, these are called args and kwargs (key word args).传统上,这些被称为argskwargs (关键字 args)。 Using a * as in *args unrolls a list and puts each list element into the function as an argument;*args中使用*展开列表并将每个列表元素作为参数放入 function; similarly, ** unrolls a dictionary and puts each dictionary key-value pair into the function (which is convenient for keyword arguments)同样, **展开一个字典并将每个字典键值对放入 function (便于关键字参数)

# 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)

For posterity the code posted in this response DOES NOT WORK and is a small test case in response to @Derek and @Erik.对于后代,此响应中发布的代码不起作用,并且是响应@Derek 和@Erik 的一个小测试用例。

I couldn't see how to put formatted code in the comment so am posting it here.我看不到如何将格式化的代码放在评论中,所以在这里发布。 Please forgive my sins!请原谅我的罪过!

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)

Called using the following incantation.使用以下咒语调用。

test_measurement1.plot_measurement(test_measurement1.data[6], test_measurement1.data[15])

Both data[6] and data[15] are numpy.arrays and get concatenated together. data[6] 和 data[15] 都是 numpy.arrays 并连接在一起。 Output below: Output 如下:

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 = {}

Also, the code errors on the line另外,就行的代码错误

if (latex_mode):

giving the error给出错误

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM