阅读本文需要15分钟
前言
本人比较在意对代码的管理,不仅是为了以后的维护,更是基于对阅读者的尊敬
具体类一般先实现功能后再优化,不要奢望一次就能写出好的代码
许多规范参照了《Clean Code》
涉及到的知识点
匿名函数(lambda函数) 点击此处查看匿名函数知识点
装饰器 点击此处查看装饰器知识点
栗子
对matplotlib.pyplot进行封装,现有一个字典,key存属性,value存值,基于这个字典画出对应的图片。
{
"x":[1,2,3,4,5,6,7,8,9],
"y":[1,2,3,4,5,6,7,8,9],
"title":"Figure",
.......
}
1.规划
文件介绍
test.xml
是方便测试临时写的一个存储所有画图有关的属性和值,真正项目时这个xml是由前端生成的
demoCmd.py
因为前端调用python我是通过命令行
调用的,所以这个文件处理前端命令,是主函数
Demo.py
这个是所有画图功能类
,供其他文件调用
CONST.py
所有有关的常量、映射放在这里,相当于是一个配置文件
。这样做的目的是当我们需要添加或删除某些功能时,只需修改CONST.py里面的对应关系,不需要再动其他文件的代码
test.xml
<?xml version="1.0" encoding="UTF-8"?>
<Values>
<x>
<value type="list">[-6.283, -6.083, -5.883, -5.683, -5.483, -5.2829999999999995, -5.082999999999999, -4.882999999999999, -4.682999999999999, -4.482999999999999, -4.282999999999999, -4.082999999999998, -3.8829999999999982, -3.682999999999998, -3.482999999999998, -3.2829999999999977, -3.0829999999999975, -2.8829999999999973, -2.682999999999997, -2.482999999999997, -2.282999999999997, -2.0829999999999966, -1.8829999999999967, -1.6829999999999967, -1.4829999999999968, -1.2829999999999968, -1.0829999999999969, -0.8829999999999969, -0.6829999999999969, -0.48299999999999693, -0.2829999999999969, -0.08299999999999691, 0.1170000000000031, 0.3170000000000031, 0.5170000000000031, 0.7170000000000032, 0.9170000000000031, 1.117000000000003, 1.317000000000003, 1.517000000000003, 1.717000000000003, 1.917000000000003, 2.117000000000003, 2.3170000000000033, 2.5170000000000035, 2.7170000000000036, 2.917000000000004, 3.117000000000004, 3.317000000000004, 3.5170000000000043, 3.7170000000000045, 3.9170000000000047, 4.117000000000004, 4.317000000000005, 4.517000000000005, 4.717000000000005, 4.917000000000005, 5.117000000000005, 5.3170000000000055, 5.517000000000006, 5.717000000000006, 5.917000000000006, 6.117000000000006]</value>
</x>
<y>
<value type="list">[0.00018530717852557836, 0.19885094075634005, 0.3895890148366298, 0.5647954043146128, 0.7174851833375362, 0.8415710922562171, 0.9321062174577968, 0.985481209200597, 0.9995681749983588, 0.9738055119787167, 0.9092202962174792, 0.8083873364566131, 0.675326524604979, 0.5153425753334286, 0.3348135438408722, 0.1409365529206157, -0.05855913361357452, -0.2557202522846237, -0.4426866114690056, -0.6120044524325037, -0.756923607169248, -0.8716666062987226, -0.9516590085381078, -0.9937117692407419, -0.9961483775425712, -0.9588716935597641, -0.8833678210493362, -0.7726468611420304, -0.6311229091091574, -0.4644380783136112, -0.2792375669548097, -0.08290473498661866, 0.11673324714446892, 0.31171744308496974, 0.4942744482509477, 0.6571262909383787, 0.793780582088022, 0.8987893463492944, 0.9679662156654169, 0.9985533265569903, 0.9893312674359778, 0.9406676926976436, 0.8545026655000147, 0.7342713135679936, 0.5847668814911388, 0.41194963918783684, 0.22270926475237623, 0.024590174730963994, -0.17450924795818812, -0.3666515376270242, -0.5441765875265056, -0.7000070341298301, -0.8279304092823339, -0.9228468117022411, -0.9809722239510984, -0.9999893692678891, -0.9791400940809049, -0.9192555931981585, -0.8227232726933746, -0.6933915715597261, -0.5364165365916276, -0.358056267069889, -0.1654214240919641]</value>
</y>
<style>
<value type="string">g-</value>
</style>
<figure>
<value type="list">[8,6]</value>
</figure>
<title>
<value type="list">['sinX Figure', 14, 'b']</value>
</title>
<xlabel>
<value type="list">["x axis",14,"b"]</value>
</xlabel>
<ylabel>
<value type="list">["y axis",17,"r"]</value>
</ylabel>
<xlim>
<value type="list">[-7,7]</value>
</xlim>
<ylim>
<value type="list">[-2,2]</value>
</ylim>
<xticks>
<value type="list">[10]</value>
</xticks>
<yticks>
<value type="list">[-10]</value>
</yticks>
<xscale>
<value type="string">linear</value>
</xscale>
<yscale>
<value type="string">linear</value>
</yscale>
<axhline>
<value type="list">[1,-1]</value>
</axhline>
<axvline>
<value type="list">[2]</value>
</axvline>
<axis>
<value type="string">on</value>
</axis>
<grid>
<value type="boolean">True</value>
</grid>
<legend>
<value type="string">best</value>
</legend>
<label>
<value type="string">plotFigure</value>
</label>
</Values>
CONST.py
FigureFeature = {
"plot":['title','xlabel', 'ylabel', 'xlim', 'ylim', 'xticks', 'yticks', 'xscale', 'yscale', 'axhline', 'axvline', 'axis', 'grid', 'legend'],
"scatter":['title','xlabel', 'ylabel', 'xlim', 'ylim', 'xticks', 'yticks', 'xscale', 'yscale', 'axhline', 'axvline', 'axis', 'grid','legend'],
}
###利用字典存lambda函数
map_function = {
"title":lambda title:plt.title(title[0],fontsize=title[1],color=title[2]),
"xlabel":lambda xlabel:plt.xlabel(xlabel[0],fontsize=xlabel[1],color=xlabel[2]),
"ylabel":lambda ylabel:plt.ylabel(ylabel[0],fontsize=ylabel[1],color=ylabel[2]),
"xlim":lambda xlim:plt.xlim(xlim[0],xlim[1]),
"ylim":lambda ylim:plt.ylim(ylim[0],ylim[1]),
"xticks":lambda xticks:plt.xticks(xticks),
"yticks":lambda yticks:plt.yticks(yticks),
"xscale":lambda xscale:plt.xscale(xscale),
"yscale":lambda yscale:plt.yscale(yscale),
"axhline":lambda axhline:plt.axhline(axhline[0]),
"axvline":lambda axvline:plt.axvline(axvline[0]),
"axis":lambda axis:plt.axis(axis),
"grid":lambda grid:plt.grid(grid),
"legend":lambda legend:plt.legend(loc=legend)
}
fun_default = lambda x:x
proper_plot = []
前端调用的cmd命令为,(也就是文件不是通过点击F5运行的,而是输入这条命令启动的)
python demoCmd.py label=plot path_xml_args=./test.xml path_xml_return=./return.xml path_picture=./test.png
demoCmd.py
import parsexml
from Demo import Demo
if __name__ == "__main__":
Error = False
args = parsexml.parse() ##解析cmd参数为字典
"""Example
>>> python demoCmd.py label=plot path_xml_args=./test.xml path_xml_return=./return.xml path_picture=./test.png
{
"label":"plot"
"path_xml_args":"./test.xml"
"path_xml_return":"./temp/return.xml"
"path_picture":"./temp/test.png"
}
"""
if args == False:
Error = True
parsexml.save({"status":0}, path_xml_return) ##写出错误结果到xml文件
#print("解析错误,注意等号左右不要有空格")
label = args.get("label",False)
path_xml_args = args.get("path_xml_args",False)
path_xml_return = args.get("path_xml_return",False)
path_picture = args.get("path_picture",False)
args_xml = parsexml.read(path_xml_args) ##解析xml为字典,数据太多就不展示了,
draw = Demo()
if label == "plot":
result = draw.plot(args_xml, filePath_png=path_picture)
elif label == "scatter":
result = draw.scatter(args_xml, filePath_png=path_picture)
elif label == "hist":
result = draw.hist(args_xml, filePath_png=path_picture)
elif label == "bar":
result = draw.bar(args_xml, filePath_png=path_picture)
elif label == "barh":
result = draw.barh(args_xml, filePath_png=path_picture)
elif label == "pie":
result = draw.pie(args_xml, filePath_png=path_picture)
else:
pass
parsexml.save({"status":0}, path_xml_return) if Error else parsexml.save({"status":1}, path_xml_return) ##写到xml文件
Demo.py
import numpy as np
import matplotlib.pyplot as plt
from CONST import FigureFeature
from CONST import map_function
from CONST import fun_default
"""定义一个画图函数装饰器"""
def addDecorate(type_):
def outer(func):
def inner(*args, **kwargs):
try:
items,filePath_png = func(*args, **kwargs)
feature = tuple(set(FigureFeature.get(type_)) & set(items.keys()))
for i in feature:
map_function.get(i,fun_default) (items.get(i,"nothing"))
plt.savefig(filePath_png)
plt.show()
except Exception as e:
print(e)
return False
return True
return inner
return outer
class Demo(MatPlotDrawFigure):
def __init__(self):
pass
@addDecorate(type_='plot')
def plot(self,items,filePath_png):
plt.figure(figsize = items.get("figure",[0,0]))
plt.plot(items.get("x",[]), items.get("y",[]), items.get("style",""), label = items.get("label","plot"))
return items,filePath_png
@addDecorate(type_='scatter')
def scatter(self,items,filePath_png):
plt.figure(figsize = items.get("figure",[0,0]))
plt.scatter(items.get("x",[]), items.get("y",[]), label=items.get("label",""))
return items,filePath_png
@addDecorate(type_='hist')
def hist(self,items,filePath_png):
plt.figure(figsize = items.get("figure",[0,0]))
plt.hist(items.get("values",[]), items.get("bins",[]))
return items,filePath_png
@addDecorate(type_='bar')
def bar(self,items,filePath_png):
plt.figure(figsize = items.get("figure",[0,0]))
plt.bar(items.get("xlabel",[]), items.get("values",[]))
return items,filePath_png
@addDecorate(type_='barh')
def barh(self,items,filePath_png):
plt.figure(figsize = items.get("figure",[0,0]))
plt.barh(items.get("values",[]), items.get("ylabel",[]), label=items.get("label",""))
return items,filePath_png
@addDecorate(type_='pie')
def pie(self,items,filePath_png):
plt.figure(figsize = items.get("figure",[0,0]))
plt.pie(items.get("proportion",[]), labels=items.get("labels",[]), explode=items.get("explode",[]), autopct=items.get("autopct",'%1.1f%%'), shadow=items.get("shadow",True))
return items,filePath_png
这里简单画出两种类型的图(不太好看,只是说明了程序是没有问题的)
plot
scatter
未完!