閱讀本文需要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
未完!