访问dict中相同类型对象的所有方法()

时间:2018-02-10 11:26:45

标签: python python-3.x matplotlib

我想直接调用dict的每个元素的属性而不进行迭代。我用matplotlib做了一个小例子,其中应创建多个数字并同时调用:

import matplotlib.pyplot as plt

class Graph(object):
    def __init__(self):
        self.figures = dict()
        self.axes = dict()
        for i in [1, 2]:
            self.figures[i], self.axes[i] = plt.subplots()

    def ax(self):
        return self.axes

    def fig(self):
        return self.figures

graphic = Graph()

graphic.ax().plot([0,1,2],[5,3,1])
graphic.fig().show()

因此应该调用graphic.ax() / graphic.fig()中的每个轴/数字。有可能采取直接方法吗?

2 个答案:

答案 0 :(得分:2)

如何从列表的所有元素调用方法(这里的字典似乎没用)这个问题显示了Is there a way to run a method for all instances of a class in python?

我们可以将它调整到matplotlib案例,如下所示。这允许例如调用graphic.axes.plot([0,1,2],[5,3,1])以将此数据绘制到所有存储的轴。

import matplotlib.pyplot as plt

class CallableContainer(object):
    def __init__(self):
        self.values = []
    def append(self,x):
        self.values.append(x)
    def __getattr__(self, key):
        def fn(*args,**kwargs):
            return [getattr(x,key)(*args,**kwargs) for x in self.values]
        return fn


class Graph(object):
    def __init__(self):
        self.figures = CallableContainer()
        self.axes = CallableContainer()
        for i in [1, 2]:
            fig,ax = plt.subplots()
            self.figures.append(fig)
            self.axes.append(ax)


graphic = Graph()

graphic.axes.plot([0,1,2],[5,3,1])
graphic.figures.tight_layout()

plt.show()

然而,如果真正的问题是如何制作不同的样式图,那么我们宁愿编写一个函数,它会生成一个图形并用所有需要的样式调用它,如下所示:

import matplotlib.pyplot as plt

def create_graph():
    fig, ax = plt.subplots()
    ax.plot([1,2,4])
    ax.scatter([1,2,3],[3,3,3])

styles = ["grayscale", "Solarize_Light2", "ggplot"]
for style in styles:
    with plt.style.context((style)):
        create_graph()
plt.show()

这会使用不同的样式创建相同图形的三倍。

enter image description here

答案 1 :(得分:1)

我仍然认为迭代图形和/或轴实例是可行的方法。如果您想要比实现课程中所需的每个功能更通用,那么您可以使用getattr函数。像这样:

import matplotlib.pyplot as plt

class Graph(object):
    def __init__(self):
        self.figures = dict()
        self.axes = dict()
        for i in [1, 2]:
            self.figures[i], self.axes[i] = plt.subplots()

    def ax(self):
        return self.axes

    def fig(self):
        return self.figures

    def call_ax_method(self, method, *args, **kwargs):
        for ax in self.axes.values():
            func = getattr(ax,method)
            func(*args, **kwargs)

    def call_fig_method(self, method, *args, **kwargs):
        for fig in self.figures.values():
            func = getattr(fig, method)
            func(*args,**kwargs)

graphic = Graph()

graphic.call_ax_method('plot',[0,1,2],[5,3,1], lw = 2, ls='-', marker='o')
graphic.call_fig_method('tight_layout')

plt.show()

顺便说一句,您并不真正需要类中的axfig方法,因为您可以直接访问这些属性。

如果您不想调用您的功能,请拨打call_ax_method'和' call_fig_method',您可以编写第二个派生自dict的类,并为其实现__call__方法:

import matplotlib.pyplot as plt

class InstanceDict(dict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args,**kwargs)

    def __call__(self, method, *args, **kwargs):
        for inst in self.values():
            func = getattr(inst, method)
            func(*args, **kwargs)

class Graph(object):
    def __init__(self):
        self.figures = InstanceDict()
        self.axes = InstanceDict()
        for i in [1, 2]:
            self.figures[i], self.axes[i] = plt.subplots()

graphic = Graph()

graphic.axes('plot',[0,1,2],[5,3,1], lw = 2, ls='-', marker='o')
graphic.figures('tight_layout')

plt.show()