Python编码风格
编写python代码的PEP8标准(http://www.python.org/dev/peps/pep-0008/)
- 每个缩进层次使用4个空格。
- 每行最多79个字符
- 顶层的函数或类的定义之间空两行
- 采用ASCII或UTF-8编码文件
- 在文件顶端,注释和文档说明下面,每行每条import导入一个模块,同时按照标准库,第三方库和本地库导入顺序分组
- 小括号,中括号,大括号,逗号之前没有额外空格
- 类命名采用驼峰命名发
完了以后可以使用pep8来检查python文件是否符合PEP8标准。
1. python中的变量不需要先定义在使用,可以直接使用,重新使用可以付给不同类型的值。
2. 变量命名遵循C语言命名规则。
3. 大小写敏感。
4. 变量引用计数。
5. del语句可以直接释放资源,变量名删除,引用计数减一。
6. 变量内存自动管理回收,垃圾收集。
7. 指定编码在文件开头加入 #--coding:UTF-8-- 或者#coding=UTF-8
In [6]: a=12 #无需定义,直接使用,python解释器根据右侧决定左侧类型 In [7]: print a 12 In [8]: id(a) #变量a在内存中的编码, Out[8]: 25014352 In [9]: type(a) #变量a的类型 Out[9]: int In [10]: b=12.33333 In [11]: id(b) #变量b在内存中所占用的内存编码 Out[11]: 25360264 In [12]: type(b) Out[12]: float In [13]: a="zhangsan" #变量a重新指向一个新的字符串 In [14]: print a zhangsan In [15]: id(a)#变量a在内存中的编码为保存“zhangsan”的地方,原来a指向的内存编码里的内容并没有立即释放 Out[15]: 139844847653680 In [16]: type(a) Out[16]: str #变量a现在指向一个字符串
python是动态类型语言,“引用”和“对象”分离,如下几个python内置函数可以帮我我们理解python的内存存储:
id() : 返回对象的内存地址
type() : 返回对象的类型
is 关键字 : 用于判断两个引用所指的对象是否相同
sys.getrefcount() :查看对象的引用计数
globals() :查看词典
python缓存了整数和短字符串,因此每个对象只存了一份,长的字符串和其他字符串可以有多个相同的对象。
In [18]: a="zhangsan is beijing" In [19]: b="zhangsan is beijing" In [20]: print(a is b) False In [21]: a=[] In [22]: b=[] In [23]: print(a is b) False
在python中,每个对象都存有指向该对象的引用总数,即引用计数(reference count),当使用某个引用作为参数,传递给getrefcount()时,参数实际上创建了一个临时的引用,因此getrefcount()所得到的结果会比期望值多1.
In [25]: import sys In [26]: In [26]: print(sys.getrefcount(a)) 2 In [27]: In [27]: from sys import getrefcount In [28]: In [28]: print(getrefcount(b)) 2
python的容器对象(container),例如表,词典等等的,可以包含多个对象,容器对象中包含的并不是元素对象本身,是指向各个元素对象的引用,对象应用对象。
引用减少
In [43]: a=1 In [44]: b=a In [45]: print(getrefcount(b)) 1558 In [46]: del a In [47]: print(getrefcount(b)) 1557
del也可以删除容器中的元素
In [48]: x=[1,2,3] In [49]: del x[0] In [50]: print(x) [2, 3]
当某个引用指向对象A,当这个引用重新指向其他对象时,对象A的引用计数减少1个。
In [51]: y=[1,2,3] In [52]: l=y In [53]: print(getrefcount(l)) 3 In [54]: y=7 In [55]: print(getrefcount(l)) 2
python的垃圾回收
简而言之,当python的某个对象引用计数将为0时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。然而垃圾回收时,python不能进行其他的任务了,频繁的垃圾回收将大大的降低python的工作效率,如果内存中的对象不多,就没有必要哦,python只会在特定条件下自动启动垃圾回收。当python运行时,会记录其中分配对象(object allocation)和取消对象(object deallocation)的次数,当两者的差值高于某个阀值时,垃圾回收会自动启动。
查看阀值:
In [56]: import gc In [57]: print(gc.get_threshold()) (700, 10, 10)
后面的两个10是分代回收相关的阀值,700是垃圾回收启动的阀值。可以通过set_threshold()重新设置阀值。
也可以手动启动垃圾回收gc.collect()
分代回收
python也有分代回收的策略(generation),这个策略的基本假设是存活时间越久的对象,我们的程序往往会产生大量的对象,许多对象很快产生和消失,但也有一些对象长期被使用。出于信任和效率,对于这样一些“长寿”对象,我们相信它们的用处,所以减少在垃圾回收中扫描它们的频率。
Python作为一种动态类型的语言,其对象和引用分离。这与曾经的面向过程语言有很大的区别。为了有效的释放内存,Python内置了垃圾回收的支持。Python采取了一种相对简单的垃圾回收机制,即引用计数,并因此需要解决孤立引用环的问题。Python与其它语言既有共通性,又有特别的地方。对该内存管理机制的理解,是提高Python性能的重要一步
简单函数
1. def是定义函数的关键字。
2. 下面的x和y为形参,不需要类型修饰。
3. 函数的定义行需要“:”
4. 函数体整体缩进。
5. 函数可以拥有返回值,若无返回值,返回None,相当于C中的NULL。
def add(x,y): z=x+y return z res=add(3,5) print(res)
局部变量和全局变量
局部变量的作用域覆盖全局变量(当局部变量定义了和全局变量一样的值的时候,全局变量就失效了。)
def p_num(): num=5 print num num=10 p_num() print(num)
结果为
5
10
函数内有局部变量定义,解释器不使用局部变量,局部变量的定义晚于被引用,就报错。(就是在编译阶段就出错了)
def p_num(): print(num) num=5 print(num) num=10 p_num() print(num)
Traceback (most recent call last):
File "/home/jiefy/work/2.py", line 6, in <module>
p_num()
File "/home/jiefy/work/2.py", line 2, in p_num
print(num)
UnboundLocalError: local variable 'num' referenced before assignment
函数内部可以直接访问全局变量
def p_num(): print(num) num=10 p_num() print(num)
10
10
[Finished in 0.1s]
函数内部修改全局变量,使用global关键字。