利用assert语句来发现问题
assert expression1 [",",expression2]
依据expression1会返回True或者False,值为False时引发AssertionError,expression2可选,用于传递具体的异常信息
注意:
- python不像C/C++,没有严格定义调试和发布模式。禁用断言:在运行脚本是加上-O标志
- python本身的异常能够处理就不要再使用断言【比如数组越界、类型不匹配、除数为0】
- 不用断言检查用户输入。较好的做法是使用条件判断,不符合输出错误提示信息
- 在函数调用后,当需要确认返回值是否合理时可以使用断言。
- 当条件是业务逻辑继续下去的先决条件时可以使用断言。
数据交换值时不推荐使用中间变量
在python中直接用
>>> x,y = y,x
充分利用Lazy evaluation
Lazy evaluation仅仅在真正需要执行的时候才计算表达式的值
- 避免不必要计算。在if x and y,x为false情况下将不再计算y;if x or y,x为true不再计算y。因此对于or应将真值可能性高的变量写在前。
节省空间,使无限循环成为可能。典型的使用延迟计算的例子是生成器表达式,尽在每次需要计算的时候才通过yield产生元素。
def fib(): a,b=0,1 while True: yield a a,b=b,a+b print list(islice(fib(),5))
尽量转换为浮点类型再做除法
当涉及除法运算时尽量将操作数转换为浮点类型在做运算
>>>g=float((4*96+3*85))/float(((4+3+2)*100))
对于浮点数的处理,其计算结果可能并不是完全准确的。对于在while中使用i!=1.5更要避免,浮点数的比较最好能够指明精度
晶体eval()的安全漏洞
Python中eval()函数将字符串str当成有效的表达式来求值并返回计算结果
函数声明 eval(expression[,global[,local]])
“eval is evil”针对的是eval()的安全性,当用户输入了不安全的字符串将造成不良后果。如果使用对象不是信任源,应尽量避免使用eval,可用安全性更好的ast.literal_eval替代【木有试过:P】
使用enumerate()获取序列迭代的索引和值
list1=['a','b','c']
for i,e in enumerate(list1):
print "index:",i,"element:",e
函数enumerate()主要为了解决在循环中获取索引以及对应值问题
enumerate(sequence,start=0)
sequence可以为序列,list、set等,函数的返回本质上是一个迭代器,可用next()方法获取下一个迭代元素
>>>e=enumerate(list1)
>>>e.next()
enumerate()函数实现
def enumerate(sequence,start=0):
n=start
for elem in sequence:
yield n,elem
n+=1
plus,要获取迭代过程中字典的key和value,应使用iteritems()方法
infodict=['name':'reindeer','age':'25']
for k,v in infodict.iteritems():
print k,":",v
is与==的适用场景
| 操作符 | 意义 |
| is | object identity 对象是否一致 同一块内存空间 |
| == | equal 检验对象值是否相等 |
编码编码呀,尽可能使用Unicode
关于文件的编码问题深有感触呀~~
Python内建的字符串两种类型:str和Unicode,公共祖先basestring。
最早的ASCII编码用一个字节8bit。我国表示汉字编码GBK。 》》》Problem:不同编码系统之间存在冲突 》》》solve:为不同的文字分配同一编码
Unicode编码系统可分为编码方式和实现方式两个层次。编码方式分为UCS-2(两个字节)和UCS-4(四个字节)。实现方式简称UTF包括UTF-7、UTF-16、UTF-32、UTF-8等
| Unicode编码(十六进制) | UTF-8字节流(二进制) |
| 000000~00007F | 0xxxxxxx |
| 000080~0007FF | 110xxxxx 10xxxxxx |
| 000800~00FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
| 010000~10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
Python处理中文字符常遇见的问题
- 读出文件内容为乱码
- 当Python源文件中包含中文字符时抛出SyntaxError异常【Non-ASCII charater ‘\xxx’ in……】
普通字符和Unicode进行字符串连接时抛出UnicodeDecodeError异常
#coding=utf-8 s = "中文"+ u"Chinese" print s抛出异常UnicodeDecodeError:‘ascii’ codec can’t decode byte 0xd6 in position 0:ordinal not in range(128)
对应上述问题:
读入的文件是用UTF-8编码形式保存的【Windows本地默认编码是CP936,被映射为GBK】,当在控制台上直接显示UTF-8时,两种编码不兼容。要解决一的问题可以使用Unicode作为中间媒介来完成转换。首先对读入的字符用UTF-8进行解码,再用GBK进行编码
>>>fhandle = open("t.txt",'r') >>>print (fhandle.read().decode("utf-8")).encode("gbk"))(1) >>>fhandle.close()decode方法将其他编码对应的字符串解码成Unicode,encode为编码
str.decode([编码参数[,错误处理]]) str.encode([编码参数[,错误处理]])编码参数
错误处理参数三种方式编码参数 ‘ascii’ ‘latin-1’ or ‘iso-8859-1’ utf-8 utf-16 错误处理参数 处理方式 strict 默认处理方式,抛出UnicodeError异常 ignore 忽略不可转换字符 replace 将不可转换的字符用?代替 plus,某些情况下 (1)会出现如下异常 UnicodeDecodeError:‘gbk’ codec can’t encode charcter u’\uxxxx’ in position0:illegal multibyte sequence——某些软件在保存UTF-8编码时在文件最开始的地方插入不可见字符BOM(0xEF 0xBB 0xBF)这些不可见字符无法被正确解析—–利用codecs模块可以处理这种问题
import codesc content = open("t.txt",'r').read() if content[:3] == codecs.BOM_UTF* content = content[3:]我记得貌似有直接用codecs打开文件的方式,用codecs提供的open方法来指定打开的文件的语言编码
bfile = codecs.open("dddd.txt",'r',"UTF-8" )对于问题二:Pyhton中默认的编码为ASCII(sys.getdefaultencoding()),文件**.py是以ASCII形式保存的。中文字符不是ASCII,源文件中未指定其他编码方式。因此,要在源文件中进行编码声明
#codnig=utf-8 or #!/usr/bin/python #!-*- coding: utf-8 -*- or #!/usr/bin/python # vim:set fileencoding=utf-8 :对于问题三:+左边为中文,类型为str,右边为Unicode字符串。连接时,Python将左边的中文转为Unicode再与右边的Unicode连接,将str转为Unicode事使用系统默认的ASCII进行解码,当编码值大于128时,不能正确处理。解决办法: 1)指定str转为Unicode时的编码方式
s = "中文".decode('gbk')+u"Chinese";2)将Unicode字符串进行UTF-8编码 `s = “中文”+u”Chinese”.encode(“utf-8”)
Unicode提供了不同编码系统之间字符转换的桥梁,要弄清字符所采取的编码方式以及正确的解码方法。对于中文字符,建议直接使用Unicode表式方式s = u"hao可爱的小鹿"。pyhton2.6后可通过import unicode_literals自动将定义的普通字符识别为Unicode字符串
构建合理的报层次来管理module
本质上每一个Python文件都是一个模块。但是将所有Python文件放在一个目录下并不好,需要合理组织项目的层次来管理模块—包(package) 包,类似目录,包除了常规的Python文件(模块)以外,还包含init.py文件,同时它允许嵌套,包结构如下:
Package/ __init__.py
Modu1.py
Modu2.py
Subpackage/ __init__.py
Modu1.py
Modu2.py
包中模块通过“.”访问。例如Package.Modu1;Package.Subpackage.Modu2。 导入方法:
直接导入一个包
import Package导入子模块或子包
from Package import Modu1 or import Package.Modu1 from Package import Subpackage or import Package.Subpackage from Package.Subpackage import Modu1 or import Package.Subpackage.Modu1
__init__.py文件的作用—1)与普通目录的区分;2)申明模块级别的import语句从而使其变成包级别可见。
在__init__.py文件中添加from Modu1 import Test【Test为Package下Modu1中得类】可直接导入类Test。如果__init__.py文件为空,当想使用from Package import * 导入所有模块时将不能生效。
__init__.py另一个作用通过定义__all__变量,控制需要导入的子包或者模块。
在Package目录下的__init__.py文件中添加:
__all__ = ['Mode1','Modu2','Subpackage']
运行from Package import * ,__all__变量中定义的模块和包被导入当前的名字空间
包——
合理组织代码
Proj/ |---README |----LICENSE |----setup.py |-----requirements.txt |-----sample/ | |----__init__.py | |----core.py | |----help.py |------docs/ | |------conf.py | |------index.rst |------bin/ |------package/ | |-----__init__.py | |------sunpackage/ | |------...... |------tests/ | |------test_basic.py | |------test_advanced.py- 避免名称空间的冲突
ATTENTION:这里的包与后面的软件包不同,这里的仅限于包含一个或一系列Python文件,为了合理组织代码。