1. 前言
防御性编程指的是为了防止代码泄露后被竞品公司窃取技术,使用一种较高级的明文加密编程方式。也可以当做一种带解密性质的时间胶囊,锻炼程序员自己的记忆能力、读代码能力等。
2. 案例分析
2.1 import
Import
里面可以多取一些喜欢的名字,也可以取简写- 原生库和三方库混着
Import
- 单
Import
和from
交错使用,增加美观性 - 模块和模块内的函数都分别导入,使用更加方便
- 相同作用的库都导入,如这里的
pathlib
和os
,又比如可以math
和numpy
换着用
python
import json as j
from pathlib import Path as P
import dicttoxml as dtx
from xml.dom.minidom import parseString as pS
import os as oasis
from json import dumps as ds
2.2 函数
- 将完全不需要组成函数的内容组成函数,没啥可说的,基本技巧
- 别写类型提示
- 注意函数名和参数名也有讲究,我个人是简洁派,whatever
python
def psd(s,did, fn,p, name,d,os):
l1 = ...
l2 = ...
l = ...
c = m.get(l)
try:
if ...:
l += "..."
except:
pass
os.append(...)
if c and c not in str(p):
...
return os
- 交替使用实参和外部的全局变量,如此处的
d
变量和全局的dt
变量实则为同一个
python
def gd(
d
):
if not oasis.path.exists(pc):
with open(pc, 'w') as lq:
lq.write(ds(d, ensure_ascii=False))
else:
with open(pc, 'r') as lq:
dc = j.loads(lq.read())
dc['...'] = dt
with open(pc, 'w') as lq:
lq.write(ds(dc, ensure_ascii=False))
- 函数调用的时候能用位置参数就不用关键字参数
python
dtx.dicttoxml(lq,True,'...',True,False,False,lambda lq:'...')
- 能用自己的函数就不用标准库/三方库的函数,比如将
.rglob("*.json")
替换为下面的函数
python
def gj(
p
):
for x in p.rglob("*"):
if x.is_file():
if x.suffix == ".json":
yield x
2.3 注释
- 适当增加一些没有意义的注释
- 注释加的位置多进行变化,避免单一
python
# 遍历JSON
for x in gj(pa):
...
for x in gj(pa): # 再次遍历JSON
...
- 在有问题的地方注释上
noqa
,如下面这里的dd
变量是循环内的一个变量,一般不在循环外调用,但是注释上noqa
,权当无事发生
python
for x in l1:
dd = ...
if dd is None: # noqa
raise ValueError("unexpected value")
2.4 if-else
- 能嵌套
if
就绝不用elif
- 能多写
if
就绝不写and
python
if ct == 0:
...
else:
if ct == 1:
if "..." in sn:
...
else:
if ct > 1:
if "..." in sn:
...
if ct == 1:
if "..." in ht or "..." in ht or "..." in ht or "..." in ht:
if no != '...':
...
else:
if "..." in ht:
if no != '...':
...
至于1个if做2件事还是2个if各做1件事,见仁见智,比如我这里就写了2次
if ct == 1:
- 如果没有那么多条件拿来判断,可以多加入一些边缘情况,如下面案例中的
dd
变量一般不会为None
,但是万一呢?同理,f
变量本来不可能超过10,但是万一呢?
python
for x in gen_json(pa): # 再次遍历JSON
r1 = j.load(x.open(encoding="utf-8"))
dd = r1["..."]
if dd is None:
raise ValueError("unexpected value")
else:
f = r1["..."]["..."] + 1
if f >= 12:
raise ValueError("...")
else:
...
2.5 变量
- 简洁有力
- 能一起创建就一起创建,不同类型变量混一起
python
pa, m,pc, dt,pb,s = P(r"..."), {...},P(r"..."), {},P(r"..."),{}
- 重复使用同样的变量名,如这里的
lq
变量最初指向一个列表(通过psd
函数更新,单看这里看不出来),之后又指向一个DOM
,最后又指向了一个Path
对象
python
lq = []
# 遍历data
for y in dl[:1]:
psd(y,dd,f,po,po.name,dt,lq)
lq = pS(dtx.dicttoxml(lq,True,'...',True,False,False,lambda lq:'...'))
udm(d.getElementsByTagName('...')[0],lq)
lq = pb/of/x.relative_to(pa).with_suffix("...")
lq.parent.mkdir(511,True,True)
lq.write_text(d.toprettyxml())
2.6 代码风格
- 从头到尾不用空行分隔或随心情添加空行
- 绝不换行,多嵌套,多用火车式代码,如这是一行代码:
python
d = pS(dtx.dicttoxml({'...': P(r1["..."]["..."]).parent.name,'...': P(r1["..."]["..."]).name,"...": P(r1["..."]["..."]).name,'...': {'...': '...'},'...': {'...': ..., '...': ..., '...': ...},'...': ...},True,'...',True,False,False))
- 不用刻意乱打空格,因为一个ctrl+alt+L就纠正过来了
2.7 异常捕获
- 将
try-except
作为if-else
的替代,可以增加两行代码:
python
try:
assert len(dl) <= 1
except:
...
- 用
try-except
包住绝大部分代码,让报错有处遁形,锻炼debug能力。如下面这段代码,数据量大的时候如果有少量报错的很难从结果端察觉:
python
for x in gj(pa):
try:
...
except:
...