分析一套源代码的代码规范和风格并讨论如何改进优化代码
Posted hallowode
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分析一套源代码的代码规范和风格并讨论如何改进优化代码相关的知识,希望对你有一定的参考价值。
前言
我的工程实践项目为金融文本数据挖掘,本项目涉及的网络爬虫、语义分析、金融相关知识。而在网络爬虫与语义分析这方面,python的案例特别多。所以我在github找了一份python的源代码,项目名叫Financial_Analysis。
看代码前
分析前我们可以查看项目目录下的README.md,在项目根目录下的README.md中会对本项目进行要给大致的分析,可是从本代码中的README.md中可以看到,作者对本项目的解释并不多,甚至都没告诉我们要运行的环境。
README正确做法
为了给他人更容易了解我们的项目,在我们上传项目的README.md中,我们应该在READEME.md中首先写关于本项目解决的问题,以及用到的技术。接下来我们则应该写出本项目需要哪些环境,最后我们则应该解释运行步骤。因为有些项目的运行过程是比较麻烦的。用详细的项目解释,给人以方便,才能获取更多的star。
分析代码
在了解完项目做了哪些功能后,我们就进入代码分析的阶段。我们要线看代码的目录结构,一般好的代码目录结构会对应它的功能模块。所以我们就可以根据目录结构知道某个功能在哪里实现,然后我们就可以逐个功能模块的代码来分析。而其他目录结构中与我们分析的功能无关,则可暂时放在旁边。
如上图的目录结构,他将项目分了三个目录。这三个目录就对应了三个功能。例如Scrapy对应分布式爬虫模块,Fama-French-choose-stock-master对应金融数据挖掘,news-emotion-master对应文本挖掘技术。当然我们可能从三个模块的文件名看不出对应的功能。例如Fama-French-choose-stock-master,乍一看是看不出来这个模块做的啥东西。
命名正确做法
我们在命名文件名或者变量名的时候,一定要做到用一个通俗的单词。不应该用拼音,也不应该随便自己弄个单词缩写。例如上面图中Fama-French-choose-stock-master中的Fama到底是什么意思呢?要用单词缩写的话,一定是大家都默认的缩写,而不是自己随便取一个缩写。如果真的要这么做,一定要在旁边写上注释。对于变量命名有时候有些语言会推荐驼峰结构,所以我们写代码的时候最好要按照语言推荐的方法去使用驼峰结构或者其他风格。
代码格式
# --------------计算SMB HML RM
def getData(mcStockDf,drStockDf,bmStockDf,sz50Df):
# 取某段时期所有股票
stocks = mcStockDf.columns.values
# 转置处理
mcStockDf = mcStockDf.T
bmStockDf = bmStockDf.T
# 选取某一列作为基准
mcStockDf = mcStockDf.iloc[:,0:1]
bmStockDf = bmStockDf.iloc[:,0:1]
# 取列名
sortName = mcStockDf.columns
# 排序
mcStockDf = mcStockDf.sort_values(by=sortName[0])
bmStockDf = bmStockDf.sort_values(by=sortName[0])
# 取当前股票总数
amount = len(mcStockDf)
# 选取大市值股票组合
B = mcStockDf[int(amount-amount/3):].index
B = B.values
# 选取小市值股票组合
S = mcStockDf[:int(amount/3)].index
S = S.values
# print(S.values)
# 选取高bm的股票组合
H = bmStockDf[int(amount-amount/3):].index
H = H.values
# 选取低bm的股票组合
L = bmStockDf[:int(amount/3)].index
L = L.values
# print(L)
# 求因子的值
SMB = drStockDf[S][1:].sum(axis=1) / len(S) - drStockDf[B][1:].sum(axis=1) / len(B)
HML = drStockDf[H][1:].sum(axis=1) / len(H) - drStockDf[L][1:].sum(axis=1) / len(L)
# print(SMB)
# 基准收益率 上证50指数
# print(sz50Df)
RM = np.diff(np.log(sz50Df['close']))-0.04/252
# print(len(RM))
X = pd.DataFrame({"RM": RM, "SMB": SMB, "HML": HML})
# 取前g.NoF个因子为策略因子
factor_flag = ["RM", "SMB", "HML"]
X = X[factor_flag]
# 对样本数据进行线性回归并计算ai
t_scores = [0.0] * amount
# 循环依次计算股票的分数
for i in range(0,amount):
t_stock = stocks[i]
sample = pd.DataFrame()
t_r = linreg(X, drStockDf[t_stock][1:] - 0.04 / 252, len(factor_flag))
t_scores[i] = t_r[0]
# 这个scores就是alpha
scores=pd.DataFrame({'code':stocks,'score':t_scores})
# 根据分数进行排序
scores = scores.sort_values(by='score')
# print (scores.sort_values(by='score'))
return scores
具体代码格式可以看到在python里面是不使用大括号的,我们是用缩进格式来控制函数范围。所以我们在控制缩进的时候一定要小心,多一个空格少一个空格就报错。而且在这里我们不推荐使用tab键缩进。因为有的地方tab缩进格式不同。所以在你本机上可能能跑,在别人的电脑上用不同的编译器可能就乱七八糟的。而且上面的这个函数一个函数就61行,这是很恐怖的。
函数的正确做法
对于函数,我们推荐的做法是一个函数应该控制在20行代码左右。这样会读者更加容易分析代码。网上就有个段子一个类中几万行代码,这样的代码我们很难以模块化的方法去阅读。而且这种很长的函数,我们应该给一个注释,注释中我们要说到代码的参数分别代表什么意思,返回值是什么东西,过程做了什么。
python语言命名特点
python命名规则与其他语言有很大的不同,例如__init__(self)函数,这种以__开头与结尾的函数我python类库中一些特殊的函数。所以我们在写一个函数时尽量不要用__开头和结尾。只以__开头的函数和变量则是代表着私有的函数与变量,但是python知识将其名称改为了_类名__name,所以我们在看到这种格式的函数与属性的时候,切记不要调用。调用则会破坏程序的封装性。而以单下划线_开头的命名一般用于模块中的"私有"定义的命名。
文件编码
由于中文的特殊性,很多时候编码格式不对,会导致别人下载代码后中文乱码。所以我们创建文件的时候一定要用UTF-8编码,这是大部分人使用的编码格式。在python中,例如在文件头重加
#encoding:utf-8
总结
根据这套代码我们能发现不少缺点,也有很多优点。但是我们眼中不能只看优点,在写代码的时候,很容易就被自己的习惯蒙蔽过去,然后导致很多部分有这样有那样的不规范。我们要想写一个好的代码,不管技术多难,写代码就像写字,要时刻记住这些规范。
以上是关于分析一套源代码的代码规范和风格并讨论如何改进优化代码的主要内容,如果未能解决你的问题,请参考以下文章