《编写高质量代码 改善python程序的91个建议》第二章 基础语法 19-35

建议19:有节制使用from...import...

               import    VS  from...import....

               import  test                  ##  test 进入局部命令空间 + 进入系统模块字典中 sys.module['test'];

               from test  import  a      ##  a 进入局部命令空间  + test进入系统模块字典中(a 不在系统模块字典中);

## test_import.py
from a import add
from b import add

# 最后起作用的是最近一次导入的函数,即不同模块相同函数存在覆盖情况;

# 命令空间冲突

##----嵌套导入----
from b import person # a.py
form a import info # b.py

建议20:用absolute import 来导入模块 from app.sub1 import testmodule, 相对导入 import  .. import testmodule在python 3中被删除(容易造成混乱);

建议21:i +=1 不等于 ++i;    ++i 语法python 解析器当作 +(+1)来处理(永远等于+1,表示正数符号)并不是自增语法; --i: - (-1) 等于1 表示两个负号;

建议22:使用 with 关闭资源; 

with open("path", "rw") as filehandle [, open("path_another", "r") as rhandle]
## f.__enter__() 进入文件上下文,生成上下文管理器对象 = f
filehandle.read()
filehandle.write()
...
## f.__exit__() 离开上下文,上下文管理器对象做清理善后工作,比如关闭 handle;

## 另外,python 还提供了 contextlib 来专门管理上下文

建议23:使用 else 简化循环;

 for/while  expr1:
     do_sth()
break
else: ## expr1 为 False时,执行else; 当 break 时,expr1仍然为True,此时不执行else; do_else_sth() ## 在遍历列表找值时,有用处;

建议24:异常处理基本原则

try:
   statment ##----不宜放入过多操作
except <name1>: ##--- 异常处理尽量精细, 子类异常先处理
   statment
except <name2,name3>: ## 异常提示要友好
   statment
except:
   statment ## 其他异常统一处理, 各种可能性都有可能,此处异常说明要慎重 || 也可将异常 raise 抛给上层
else:
statment ## 没有异常
finally:
statment ## 不管是否有异常,依然会执行

建议25: 小心 finally 中的陷阱

       情况1: 如果 异常没有被except处理,将会临时保存起来,执行finally后再抛出;但如果finally也抛异常或者有return 或 break时,临时异常会被丢弃或者覆盖; 

# 情况2:
try
: if a <= 0: raise ValueError
else:
return a ## return a 之前先执行finally语句块,如果 finally 有return,那么该return a 失效
except ValueError:
print(a)
finally:
print("End")
reutrn -1;

建议26:深入理解 None, 正确判断对象为空

#### python 判断为空的情况汇总 ####

None # 是一个常量,单例对象,类名 NoneType, 任何 None 都相等,固定id, id(None)
False # 常量
0、0L、0.0 #等,任意0数值类型
'' () [] {} #空序列

即,空值有很多种,但 相互都不is相等(  [] is None  ==> False);

list1 = []
if list1:            ## 会调用 list1.__nonzero__方法来判断,返回 0/1 或者 True/False
print(list1) ## 没有 __nonzero__ 方法,会调用 __len__ 方法 ,返回 0/1
## __nonzero__ 和 __len__ 都没有 ,返回 True

建议27:字符串连接优先考虑 join 而不是 +;

          ’‘.join(strlist)  (一次性加起来) 优优优于于于  result += strlist[i] (逐个加起来)

            python 中的字符串是不可变对象; str1 + str2  每次都要申请一块新内存来存放结果;join 是一次性申请一块总大小地址,一次性存放;

建议28:格式化字符串优于使用format 而不是 %: fomat 使用更灵活,可不按顺序。以后会直接取代%成为标准;

##--------- % 格式化 -------------
"%s" % "chaoren" ## 单个参数直接格式化
"%s %s %s" % ("Hello", "World", "chaoren") ## 元组形式
"%(key)s -- %(value)f" % dict1 ## 字典形式

##---------- format 格式化 -----------
"xxx {0} xxx {2}, xxx {1}".format("hello", "world", "!!!") ## 引用元组位置
point = (1,3)
"X:{0[0],xxx, Y:{0[0]}".fomat(point)
"test %s"%(point,)
## 格式化规则百度

 (tuple) 与 (tuple,) 前者表示一个加了括号的对象, 后者表示一个元组。加一个逗号表示区分是元组。

建议29:区别对待可变对象与不可变对象

          对象属性:id,  type   及  值。

          不可变对象:数字,字符串,元组;

          可变对象:字典, 列表, 字节数组,集合;

          在类函数中,默认参数仅仅被评估一次。每次分配新对象时,会使用上次的参数结果!改进:default=None, if default is None:default=[]   self.default=default

         【对于浅拷贝和深拷贝:对可变对象与不可变对象的之间的不同】

建议30:[]  ()  {} 一致的容器初始化形式

##---- 列表解析 形式----##

[x for x in xlist] ##一维列表

[[x.upper() for x for x_list] for x_list in xx_list] ##二维列表

[(a,b) for a in a_list for b in b_list if a==b] ## 多重迭代

[f(x) for x in x_list if x>0] ## 遍历 for + if
   [ x**2 if x%2==0 else x+1 for x in x_list if x>0]  ## for + if + fun  遍历加计算
= [(x**2 if x%2==0 else x+1) for x in x_list if x>0]

## 建议用列表解析式 [ ...... ], ''.append(): 较耗时,因为每次需要开辟新空间来存储最新结果;

 建议31:  函数传参既传值也不是传引用

   

 

 

 

 

 

posted @ 2019-12-05 18:13  一花一世界V5  阅读(168)  评论(0编辑  收藏  举报