代码优劣
优质代码特点: 高效、鲁棒性、简洁性、可共享、可测试、可移植、可监控、可运维、可扩展
- 代码的正确性和性能
- 代码的可读和可维护性
- 代码的可运维和可运营
- 代码的可共享和可重用
劣质代码(看来我一直写的就是劣质代码hhh)
编写优质代码的流程
在实际工作中,编码时间只占项目整体时间的10%左右.
好的代码是多个环节共同作用的结果.
-
编码前: 需求分析、系统设计
-
编码中: 编写代码、单元测试
-
编码后: 集成测试、上线持续运营/迭代改进.
一个好的系统/产品是上述过程持续循环的结果.
需求分析和系统设计
在软件开发中经常被忽视或轻视.然而好的需求分析和系统设计可以节省大量人力物力.
前期最多的投入 收益往往最大 |
需求分析
- 定义系统/软件的黑盒行为(外部行为,能做什么external,what)
- 用简练的语言勾勒系统功能.包括系统类型描述、系统规模描述、系统定位和系统差异描述、系统对外接口功能描述.
- 需求分析用精确的数字描述
系统设计
-
设计系统/软件的白盒行为(内部行为,怎么做 internal,how/why)
-
系统架构:
-
注意系统设计的约束: 计算/存储/网络/IO资源限制
-
需求是系统设计决策的来源 系统设计的风格
-
系统设计的风格:如CISC和RISC
- 好的系统是在合适假设下的精确平衡,一个通用的系统在某些方面不如专用系统.
- 子系统功能的单一是复用和扩展的基础。
- 子系统和模块间关系应该简单而清晰软件中最复杂的是耦合.
- 接口
- 接口修改时主要注意 :理好用、修改时需要向前兼容(老版本不受新版本影响
写好代码
项目的维护成本高于项目的开发成本.项目的50%时间都是用于沟通.
代码书写过程中的细节问题
-
模块(程序的基本组成单位): 一个.py/.c/.go就是一个模块,需要有明确的功能,做到高内聚低耦合,需要考虑怎样切分模块
-
数据类的模块: 完成对数据的封装,通过内部变量实现 过程类的模块: 本身不含数据,读取执行相关操作,以及调用其他模块.
-
模块内部组成: 要刻意分离独立函数和成员函数,不要过多依赖成员函数.
-
-
面向对象: 本质是数据封装.写程序要从数据角度考虑,而不是执行过程.
- 慎用多态和继承!!很好的继承模型是基于对需求的准确把握
-
代码注释: 先写注释,后写代码.
-
代码块: 一个函数内的代码实现.把代码的段落分清楚.形成的背后是逻辑(段落划 分,层次),常用空白符表达代码逻辑符号.
-
命名:准确易懂(可采用标准命名法如驼峰命名法、下划线命名法).
优秀的软件工程师
成为优秀的软件工程师
外部因素: 工作时间、代码量、学历、就职经历.
内部因素
-
学习——思考——实践: 活到老学到老;做过的项目要复盘写体会;在学习和思考的 基础上,多做项目,把学到的理论运用到真正的工作中,实现知识的转化.
-
知识——方法——精神: 找到分析、解决问题的适合自己的方法.在遇到困难和挫 折时,要坚定自己的信念,保有精神. 自由精神、独立思想、对完美的不懈追求.
-
基础知识是根本: 包括数据结构与算法、操作系统、系统结构、计算机网络、软 件工程、编程思想、逻辑思维能力、归纳总结能力、表达能力、研究能力、分析 问题解决问题能力.
-
有着改变生活,改变世界的梦想,而不是学习编程和炫耀技术.
- 精神
- 自由精神 独立思想:人一定要有自己的思想
- 对完美的不懈追求:不能做到一定程度就满意了,要不断追求更好的结果
最后
在写代码的过程中,我们需要综合全方位的能力,包括把握问题、建立模型、沟通协 助、编码执行的能力等.
要培养一定的品位,能区分代码的优劣,并有目的地学习好多代码,调整自己的行为,提高自己的编码能力.
代码是写给别人看的,别人看不懂或不愿意看,则代码本身就是失败的.
Mini-Spider
退出函数:使用python自带task_done和join
-
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
-
Queue.join() 实际上意味着等到队列为空,再执行别的操作
-
说明:每task_done一次 就从队列里删掉一个元素,这样在最后join的时候根据队列长度是否为零来判断队列是否结束,从而执行主线程。
(ps:现在还看不懂以后再来补充吧)
爬虫的主逻辑编码
将代码按步骤合理划分,便于理解和阅读
- 第一步:从队列中拿到数据
- 第二步:读取数据
- 第三步:保存数据
- 第四步:求深度,如果深度不足就
- 第五步:继续解析
- 第六步:结束任务
Python代码检查规则
代码风格规范
-
程序规模规范
- 每行少于120字
- 函数长度不得超过120行
-
缩进规范
- 不使用Tab而是4个空格
- 单行内容拆成多行时,与首行保持对齐或首行留空,从第二行起缩进4个空格
-
空格规范
-
括号内不添加空格
-
参数列表: 索引或切片的左括号前不应加空格
-
, : ; 前不添加空格,而是在之后添加一个空格
-
-
所有二元运算符前后各加一个空格
-
关键字参数或参数默认值的等号前后不加空格
引用规范
https://www.cnblogs.com/Zzbj/p/9607462.html
- 禁止使用from … import … 句式,直接导入类或函数,而是应该在导入库后再行调用.
import 模块:导入一个模块;注:相当于导入的是一个文件夹,是个相对路径。
把这个模块中用到的名字都收录到新开辟的空间中
from…import:导入了一个模块中的一个函数;注:相当于导入的是一个文件夹中的文件,是个绝对路径
-
每行只导入一个库
-
按照标准库、第三方库、应用程序自有库顺序排列,用一个空行间隔.
- 应避免使用通配符进行import,即from xxx import *
定义规范
-
变量定义规范
- 局部变量: 下划线命名 + 全部小写
- 全局变量: 写在文件头部
- 常量: 下划线命名 + 全部大写
-
类定义规范
-
类名: 首字母大写驼峰命名法
-
成员
-
- 保护成员: 单下划线前缀
- 私有成员: 双下划线前缀
- Python 没有任何机制可以有效地限制对任何实例变量或方法的访问.Python 规定了在变量/方法的名称前加上单下划线或双下划线的约定,以模拟受保护和私有访问说明符的行为。
python编写惯例
-
if __name__ == '__main__':
当模块被直接运行时,以下代码块将被运行,当模块是被导入时,代码块不被运行。
-
巧用in
# 单个字符 a='hello' b='world' if ('l' in a): print('l 在a 内') # 连续多个字符 if ('ld' in b): print('ld 在b内') # 元组 tup=(1,2,3,4) # 列表 list=[1,2,3,4] # 集合 sets={1,2,3,4} # 字典 dicts={'a':1,'b':2} if 1 in tup: print('元组内有1') if 1 in list: print('列表内有1') if 1 in sets: print('集合内有1') if 'a' in dicts: print('字典内有a')
-
用序列创建字符串
-
Python 中的字符串为引号之间的字符序列集合,Python 没有字符类型。
-
用空字符串和join()构造字符串
str = ""; seq = ("a", "b", "c"); # 字符串序列 print str.join( seq ); >>seq="abc" #join通过指定字符连接序列中元素后生成的新字符串
-