我正在为我的样式图开发产品的类层次结构,对我的目的有用,
当我尝试从子类实例化绘图时,我收到了标题为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(最后一条注释行),则一切正常!我不知道我错了!
我该如何修理?
答案 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]
的样式与此列表相同,该样式无效(样式应为字符串)