地块层次结构中的Python错误:TypeError:无法散列的类型:'list'

时间:2018-08-02 09:44:39

标签: python matplotlib

我正在为我的样式图开发产品的类层次结构,对我的目的有用,

当我尝试从子类实例化绘图时,我收到了标题为TypeError: unhashable type: 'list'的错误报告, 为了简化错误,我简化了该类,但是可以使用和测试这些类,尤其是仅当我尝试从子类中调用时,才收到此错误,因为我调用了我没有得到的顶级类然后剧情就产生了 现在让我报告几个课程:

层次结构以抽象类开头:

from abc import ABCMeta, abstractmethod
import matplotlib.pyplot as plt
import numpy as np
from abc import ABCMeta, abstractmethod
from cycler import cycler

class BasePlot(metaclass=ABCMeta):

   def __init__(self, title : str = ' ' , filename : str = ' '):
      self.title = title
      self.filename = filename   

   def schemes(self, style:str = 'nb'):
         color = {} 
         color['nb']   = ['#8DA0CB', '#E58AC3', '#A6D853', '#FFD930', '#B2B2B2', '#5FC3A4', '#FC8D62', '#66C2A5']
         return color[style]

   def linestyles(self, style : str = 'ls1'):  
         linestyles = {}
         linestyles['paper'] = [(0, ()), (0, (3, 1, 1, 1, 1, 1)), (0, (5, 5)),(0, (5, 1)),(0, (3, 5, 1, 5)),(0, (3, 5, 1, 5, 1, 5)),(0, (1, 1)),(0, (5, 10)) ]
         return linestyles[style]                                                                                                   

   @abstractmethod
   def style(self,*args,**kwargs):
      pass

从该基类继承了一个类,其中几乎定义了我需要的所有东西,该类被称为产生默认图的默认类!

 class DefaultPlot(BasePlot) :

    def __init__(self, figsize,*args,**kwargs):
        self.var = [*args]
        self.params = kwargs
    def style(self,*args):
        self.variable = [*args]
    def cycle(self,n : str):
            if n == '0':
                  return plt.cycler("color", self.parameters['scheme'])      #colors)         
            elif n=='1':
                  return plt.cycler("color", self.parameters['scheme']) + plt.cycler("linestyles", self.parameters['linestyles'])
    def setparams(self, kwargs):
             self.parameters = kwargs
             if 'scheme' in self.parameters.keys():
                 v = self.parameters['scheme']  
                 self.parameters['scheme'] = self.schemes(v)

             if 'font' not in self.parameters.keys():
                self.parameters['font'] = 'serif'
             if 'scheme' not in self.parameters.keys():
                self.parameters['scheme'] = self.schemes('nb')
             if 'cycle' not in self.parameters.keys():
                self.parameters['cycle']  = self.cycle('0')
             if 'linestyles' not in self.parameters.keys():
                self.parameters['linestyles'] = self.linestyles('paper')


             myparams = {
               'axes.prop_cycle': self.parameters['cycle'],     
               'grid.color' : 'gray',
               'font.family': self.parameters['font'] ,
               'font.style' : 'italic'
             }

             plt.rcParams.update(myparams)

    def __call__ (self,nrows,ncols,*args,**kwargs):

       self.style(*args)
       self.setparams(kwargs)

       if nrows == ncols ==1:
            self.fig, self.axs = plt.subplots(nrows,ncols,figsize=(9.5,4.5))
       else:
            self.fig, self.axs = plt.subplots(nrows,ncols,figsize=(12,6))
       for i in range(nrows):
          for j in range(ncols):
             if nrows == ncols == 1:
                 self.axs.set_title('', color='#555555')
                 legend = leg = self.axs.legend()

             else:
                 self.axs[i,j].set_title('', color='#555555')
                 legend = leg = self.axs[i,j].legend()
             legend.get_frame().set_linewidth(1.2)
             plt.setp(legend.get_texts(), color='#555555')

             if nrows == ncols ==1 :
                plt.subplots_adjust(left=0.125 , bottom=0.125, right=0.95, top=0.87, wspace=0, hspace=0)
             else:   
                plt.subplots_adjust(left=0.06 , bottom=0.1, right=0.95, top=0.95, wspace=0.2, hspace=0.4)
       return self.fig,self.axs

最后,我继承了最后一个级别的类,该类的目的(即使在这里看起来也不是)是替换上面默认类中定义的参数,以便创建这样的几个类来生成样式图(基本上在这一步中,我替换了颜色..字体的刻度等)

class Standard(DefaultPlot):

def __init__(self , figsize , *args , **kwargs):
    self.args = [*args]
    self.params = kwargs
    super().__init__(figsize,*self.args, **self.params )

def setparams(self, kwargs):

         self.parameters = kwargs
         if 'scheme' in self.parameters.keys():
              v = self.parameters['scheme']  
              self.parameters['scheme'] = self.schemes(v)
         if 'linestyles' not in self.parameters.keys():
            self.parameters['linestyles'] = self.linestyles('paper')
         if 'scheme' not in self.parameters.keys():
            self.parameters['scheme'] = self.schemes('nb')
         if 'cycle' not in self.parameters.keys():
            self.parameters['cycle']  = self.cycle('0')

         super().setparams(self.parameters)

并从主脚本中调用该类:

import numpy as np
import matplotlib.pyplot as plt
#import defaultplot 
import qualityplot

def main():

    x = np.linspace(0,2*np.pi,50)
    y = np.sin(x)

    fig,axs = qualityplot.Standard(figsize=(9.5,4.5))(1,1,**{'scheme':'nb'})
    #fig,axs = defaultplot.DefaultPlot(figsize=(9.5,4.5))(1,1,**{'scheme':'nb'})

    axs.plot(x,y)
    plt.show()

现在,如果您尝试运行并调用qualityplot,则会收到错误:TypeError: unhashable type: 'list',但是如果您调用顶级defaultpolot.DefaultPlot(最后一条注释行),则一切正常!我不知道我错了! 我该如何修理?

2 个答案:

答案 0 :(得分:1)

该错误告诉您不能将列表用作字典键。即以下是不可能在python

a = {[1,2,3] : "A"}

在您的代码中,由于更改了self.parameters['scheme']的类型,因此出现了此问题。它可能首先是字符串,然后在以下代码中转到列表。

     self.parameters = kwargs
     if 'scheme' in self.parameters.keys():
          v = self.parameters['scheme']  
          self.parameters['scheme'] = self.schemes(v)

现在在super方法中第二次调用此代码,其中self.parameters['scheme']已经是列表。在这种情况下,self.schemes(list)无效,将导致错误。

答案 1 :(得分:0)

schemes函数中,将color ['nb']设置为列表。

Standard.setparams函数中,将此列表放入self.parameters['scheme']中,然后调用DefaultPlot.setparams

DefaultPlot.setparams中,您呼叫BasePlot.schemes(v)的v等于此列表

BasePlot.schemes中,您呼叫return color[style]的样式与此列表相同,该样式无效(样式应为字符串)