写点什么

这些常见的 python 编码习惯,你都会吗

  • 2024-01-09
    广东
  • 本文字数:3811 字

    阅读完需:约 13 分钟

这些常见的python编码习惯,你都会吗

本文分享自华为云社区《不得不知的十个常见PY编码习惯》,作者:码乐。

简介


语言在发展和变化,编码习惯也在发生改变。这里简单聊聊 17 个 python 中常见的编码习惯或者风格。

1,可变数据结构: 注意在函数变量不要使用它


def foo(x=[]):	x.append(1)	print(x)            >>>foo()[1]
>>>foo()[1,1]
>>>foo()
[1,1,1]
def foo(p=None): if p is None: p = [] p.append(1) print(p) foo()[1]foo([2,3,4])[2,3,4,1]
复制代码

1.1 模块的循环导入


我们定义一个老王模块,再定义一个小李模块,相互导入时,将报错


# laowang.pyimport xiaolicount =4def main():	wilma.pr('Hello')if __name__ == '__main__':	main()            # xiaoli.pyimport laowangdef pr(str):	print(str*fired.count)if __name__== '__main__':	pr("Ok")
复制代码


导入问题,如果在使用其他语言 比如 shell 脚本引用 python 代码时,需要将 python 项目加入 linux 环境变量。 <=python2.7


export PYTON_PATH=$PYTHON_PATH:/xxx/xxx/XXXProject
复制代码


或者编辑 python 虚拟环境,添加 setup.py, 然后执行 python install -e .

1.2 基础规则


该次执行不缓存 sys.stdout,直接输出控制台


@参数 -u unbuffered
复制代码


执行时带参数 m,以 Script 方式执行 py 模块


@参数 -m 
复制代码


跳过 py 模块第一行,允许使用非 unix 形式


@参数 -x
复制代码


实体具体选项(set implementation-specific option)


@参数 -X
复制代码


程序读取文件内容并执行


file 
复制代码


程序从 stdin 读取


@参数 -
复制代码


python3 --help # 显示所有参数


dd

2, 内存管理


python 内存回收 基于 引用计数 和 分级回收。

2.1 小的整数 和短小字符,python 将缓存以便重复使用


并且 is 关键字,用于判断两个引用所指对象是否相同


    >>> a = 'gd'>>> b = 'gd'>>> a is bTrue
复制代码


== 只判断值是否相同


    a2 = []b2 = []>>> a2 is b2False>>> b2 == a2True
复制代码

2.2 对象引用时 python 基本构成方式


赋值的本质 a=1,实际上时修改 globals()字典的值,局部变量值的修改 locals()的访问和修改


>>> a1	very good man>>> globals()['a1'] = 'bad good mm'>>> globals()
复制代码

2.3 引用对象 reference count


sys.getrefcount() 查看对象的引用计数,sys.getrefcount()在查看某个引用时将创建一个临时引用,所以引用计数将多 1


    >>> c=[1,2,3]
复制代码


getrefcount© #这里 c 只有一次引用,但是计数时 2,因为当前查询有一次临时引用


   2
复制代码


引用计数的减少和增加


   >>> d=c
复制代码


getrefcount© # 增加引用 d,计数 3


     3
复制代码


del d #删除引用 d,c 的引用计数又重新为 2

2.4 垃圾回收机制 garbage collection


垃圾回收时 py 独占进行的,大大降低 py 效率,特定条件下自动启动垃圾回收。


手工回收 gc.collect()


py 运行时分配对象 obj allocation 和取消分配对象 deallocation 次数被记录,高于垃圾回收阈值,启动垃圾回收


gc.get_threshold()查看该阈值,gc.set)threshold()重新设置该阈值


(700, 10, 10) 700 表示启动垃圾回收阈值,10,10 表示分别回收的阈值

2.4.1 垃圾回收分代策略 generation,基本假设如下


存活时间越久,越不可能在后面程序中变为垃圾。 这样所有对象分为 0,1,2 三代,所有新建对象都是 0 代。


某一对象经历垃圾回收,仍然存活,那么它就被归入下一代对象。


垃圾回收时,一定扫描 0 代对象,如果 0 代经过一定次数垃圾回收,下一次对 0 代和 1 代扫描清理,


当 1 代也经历一次次数垃圾回收,这启动 0,1,2 所有对象的扫描


以上 gc.get_threshold()返回(700,10,10)两个表示每 10 次 0 代垃圾回收,将配置 1 次 1 代垃圾回收,每 10 次 1 代垃圾回收,才有 1 次 2 代垃圾回收。

2.4.2 两个对象相互引用


相互引用构成引用环 reference cycle,该引用环将给上一节 2.4.1 的垃圾回收带来困难,


引用环可能构成一些无法使用但引用计数不为 0 的对象 为了回收该引用环对象,


py 复制了每个对象的引用计数为 gc_ref 遍历所有对象,将每个对象引用的对象相应的 gc_ref 减 1,遍历结束后,


gc_ref 不为 0 的对象和这些对象的引用对象,以及继续更新下游引用对象,被爆了,其他对象被回收。


参考 内存管理,函数默认参数,动态类型

2.4.3 迭代


可迭代对象 iter


迭代器 iter + next


生成器 特殊迭代器 yield


          def yd():		a = 100		yield a		yield a*8		yield 8000
复制代码

2.4.4 抽象方法*(函数)


对象方法(self.对象方法),类方法(@classmethod),静态方法(@staticmethod)


抽象方法 需要子类实现的方法 用 @abc.abstractmethod 以及 metaclass = abc.ABCMeta 使得任何继承自父类的子类必须覆盖实现抽象方法,否则抛出异常

3,其他概念


闭包 closure


闭包指的是 难以读取其他函数内部遍历的函数


实现: 定义在函数内的内部函数可以读取外层函数变量,从而实现闭包

4,惯例


1,判定 dict 的 key 是否存在,使用 key in dict 而不用 has_key


2,not 的位置,使用 key not in dict 而不用 no key in dict


3, 使用 dict.get(key[,default])如果 key 存在,返回,否则返回 default


4, 数组字典初始化


 dic = {} for k,v in data:	 group = dic.setdefault(key,[])  #如果存在,返回dic[key],不存在把dic[key]设为defalut并返回	 group.append(v) from collections import defaultdic	 dic = defalutdic(list)	 for (k,v) in data:		 dic[key].append(v)  #所有key都有一个默认值
复制代码


迭代一个数组,使用 for i,e in enumerate(array) 而不是 for i in range(len(array))


  enumerate 还有第二个参数
复制代码

5,py3 元组 unpack


    first, second,*rest, last = range(10)    0	1	2~8		9
复制代码

6, 函数参数传入


    def foo(x,y):    	print(x,y)    adict = {'x':1, 'y':2}
复制代码


foo(**adict) #字典 key 作为参数名传入参数值


  alist=[1,2] foo(*alist)
复制代码

7, 字符串连接


    name = "Wang" "Hone"  # WangHong
复制代码

8, 解释器中的


上一次接收器的返回值
复制代码

9,嵌套列表推导式


 [(i,j) for i in range(3) for j in range(i)]
复制代码

10, print 重定向


print >>open('a.txt', 'w+'), 'hello,world'
复制代码

11,反射


#检查是否某个自定的类
isinstance(obj, class)
复制代码

12,Picking 是 Python 数据结构的序列化过程


存储一个对象,稍后再取出读取


如何 pickle 已存在的对象类型到文件


    json = {'name':'jack', 'age':100}json_file = open('json pkl', 'rb')pickle.dump(json.json_file)json_file.dump(json,json_file)json_file.close()
复制代码


取出


data=pickle.load(json_file)print(data)json_file.close()
复制代码


pickler 内建类型和外部方法


类自定义行为


	__getinitargs__(self)  #	__getnewargs__(self)
复制代码


Slate 记住它曾经是什么,以及什么时候赋值给它 ?


 __slate__
复制代码


为对象类 提供限制,只能赋予固定的属性名称

13,对象模型 Python3 和 Python2.x 之间的主要区别


Python3 的 string 和 unicode 区别不复存在,因此__unicode__被取消 __bytes__加入进来(与


python2.7 的__str__和__unicode__行为类似),用于心的创建字节数组的内建方法


py3 默认除法变成了 true 除法,因此__div__取消


__coerce__被取消,因为与其他魔法方法有功能重复 cmp 取消,与其他魔法方法功能重复__nonzero__被重命名为


bool

14,断点


6.1, 断点设置后,代码执行到该位置,程序挂起检查程序行为6.2, 异常断点,到达断点后要执行的操作6.3,  断点属性,达到断点时要执行的操作	  挂起策略,用于定义在遇到断点时是否必须挂起应用程序	  对其他断点的依赖,	  何时必须击中断点6.4   消息记录	断点命中消息,命中断点时,控制输出一条日志消息	堆栈跟踪 断点的堆栈跟踪将命中打印到控制台
6.5 断点工具 pdb 交互式代码调试,功能包括 设置断点,单步调试,进入函数调试,查看当前代码,查看栈片段,动态改变变量的值 进入pdb交互界面 命令 break 或b设置断点 continue 或c 继续执行 list或l 查看当前代码段 step或s 进入函数 return或r 执行代码直到当前函数返回 exit或q 中止并退出 next或n 执行下一行 pp 打印变量的值
复制代码

15, 依赖问题


pycurl 需要 contos 7 安装 python3-devel 具体过程 pycurl-centos7

16, py 编译 发布流程


1,编译生成 pyc 文件,建议增加-O 优选项


python3 -O -m compileall -b .


2, 删除 py 文件


   find . -name "*.py"|xargs rm -rf
复制代码


3, 删除__pycache__目录


   find . -name "__pycache__" |xargs rm -rf
复制代码


4, 打包 tar 包


    cd ..tar -cjvf xxx.1.1.00.tar.bz2 xxx
复制代码


5, 或 git push 到仓库


  git push origin master:master
复制代码

16 常用内置 魔法函数


iter # 在类中实现,可以直接对类进行迭代 类似于如下形式


            obj.next 或  next(obj)
复制代码


call # 在对象直接 进行调用


            obj()
复制代码


slate 为对象类 提供限制,只能赋予固定的属性名称


__qualname__  # 查看类和当前函数名
>>> D.f.__qualname__ >>> D.f#返回类和函数
复制代码


通过类字典返回函数,不会 返回函数名


	>>> D.__dict__['f']	<function D.f at 0x000001F6C6224670
复制代码


通过类实例的点运算 查看函数 将直接返回函数


>>> d = D()>>> d.f		<bound method D.f of <__main__.D object at 0x000001F6C5F42070>>
复制代码


查看实例的函数对象


>>> d.f.__func__<function D.f at 0x000001F6C6224670>>>> d.f.__self__<__main__.D object at 0x000001F6C5F42070>
复制代码

17 内置函数 二进制运算


chr	返回整数 i 的字符串格式,如 chr(97) 返回字符 'a' 是 ord的逆运算	chr('8364') (欧元符号)返回  €ord	返回代表单个Unicode字符的 码点的整数,例如 ord('a')返回整数 97	ord('€') (欧元符号)返回 8364 
复制代码


点击关注,第一时间了解华为云新鲜技术~


发布于: 27 分钟前阅读数: 5
用户头像

提供全面深入的云计算技术干货 2020-07-14 加入

生于云,长于云,让开发者成为决定性力量

评论

发布
暂无评论
这些常见的python编码习惯,你都会吗_Python_华为云开发者联盟_InfoQ写作社区