Python 中的列表(大小可变的数组)和字典(哈希表)就是内建于语言本身的。在核心语言中提供这些重要的构建单元,可以鼓励人们使用它们, 缩短开发时间与代码量,产生出可读性更好的代码。C不提供, c++功能不够简洁。
面向对象,
可升级:Python 提倡简洁的代码设计、高级的数据结构和模块化的组件,确保灵活性、
一致性并缩短必要的调试时间
扩展性:兼容扩展c和java
易读写,易维护
健壮性:Python 提供了“安全合理”的退出机制, Python由于错误崩溃,解释程序就会转出一个“堆栈跟踪”,那里面有可用到的全部信息,包括你程序崩溃的原因以及是那段代码(文件名、行数、行数调用等等)出错了。这些错误被称为异常。如果在运行时发生这样的错误,Python能够监控这些错误并进行处理。描述错误的类型和位置,还能指出代码所在模块。
快速原型开发工具:Python 标准库是很完备的,如果你在其中找不到所需,那么第三方模块或包就会为你完成工作提供可能。
内存管理器
内存管理是由 Python 解释器负责。C 或者 C++最大的弊病在于内存管理是由开发者负责的,会分散精力
解释性和(字节)编译性
类似于Java, Python是字节编译的,可以生成一种近似机器语言的中间形式,提升性能。
Python官网:http://python.org
编译Python
Unix 中,可执行文件通常会将 Python 安装到/usr/local/bin 子目录下,而库文件则通常安装在/usr/local/lib/python2.x 子目录下
运行Python
命令行和脚本模式(解释器执行)
命令行选项:
-d 提供调试输出
-O 生成优化的字节码(生成 .pyo 文件)
-S 不导入 site 模块以在启动时查找 Python 路径
-v 冗余输出(导入语句详细追踪)
-m mod 将一个模块以脚本形式运行
-Q opt 除法选项(参阅文档)
-c cmd 运行以命令行字符串形式提交的 Python脚本
file 从给定的文件运行 Python 脚本(参阅后文)
脚本头部添加“#!/usr/local/bin/python”正确的安装位置,可以找到python,否则给出错误提示。或者借用unix下env环境变量设置
#!/usr/bin/envpython
设置好后,不用显式的调用Python 解释器,直接输入脚本名,脚本首行书写的启动指令会自动执行。
Python集成开发环境
Eclipse,pycharm,idle等等,自己搜下.
Python语言使用细节总结
1、下划线(_)在解释器中有特别的含义
表示最后一个表达式的值。 所以上面的代码执行之后,下划线变量会包含字符串:
Python 用下划线作为变量前缀和后缀指定特殊变量
_xxx 保护变量不能用’from module import *’导入
__xxx__ 系统定义名字的专用方法
__xxx 类中的私有变量名
程序员避免用下划线作为变量名的开始。
“单下划线” 开头的成员变量叫做保护变量,是只有类对象和子类对象自己能访问到这些变量。这种变量不能直接访问,需通过类提供的接口进行访问,不能用“from xxx import *”而导入。
只以“双下划线”开头的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。
以双下划线开头和结尾的如__foo__,是特殊方法标识,如 __init__()代表类的构造函数。
2、print 语句,与字符串格式运算符( % )结合使用,
可实现字符串替换功能,类似C语言:
>>> print "%s is number %d!" % ("Python",1)
Python is number 1!
3、Print 语句也支持将输出重定向到文件:
符号 >> 用来重定向输出,将输出重定向到标准错误输出:
import sys
print >> sys.stderr, 'Fatal error: invalid input!'
import sys
print >> sys.stderr, 'Fatal error: invalid input!'
将输出重定向到日志文件的例子:
logfile =open('/tmp/mylog.txt', 'a')
print>> logfile, 'Fatal error: invalid input!'
logfile.close()
4、交互式解释器中获得帮助
内建函数help()得到一个生疏函数的帮助,用函数名得到相应的帮助信息
>>>help(raw_input)
Help onbuilt-in function raw_input in module __builtin__:
raw_input(...)
raw_input([prompt])-> string
5、注释用#
注意,文档字符串的特别注释,是运行时访问,用来自动生成文档,如def foo():
"This isa doc string."
return True
函数名下一行,如果内容多,用三个单引号“’”,就可以跨行了
6、运算符
+ - * / // % **
两种除法运算符,单斜杠用作传统除法,双斜杠用作浮点除法(对结果进行四舍五入)
双星号(**)为乘方运算符,如3 ** 2结果为9
7、比较运算(返回布尔值True、False)
< <= > >= == != <>
8、逻辑运算符(and、or、not,返回布尔值)
9、变量和赋值
不许类型关键字,直接复制
>>>miles = 1000.0
>>>name = 'Bob'
>>>counter = counter + 1
支持增量赋值
n = n * 10
n *= 10
不支持自增 1 和自减 1 运算符,--n 解释为-(-n) 从而得到 n , 同样 ++n 的结果也是 n.
10、五种基本数字类型
int (有符号整数)
long (长整数) : 长整数后缀 “L”如 2001L
bool (布尔值)
float (浮点值)
complex (复数)
Python 的长整数所能表达的范围远远超过 C 语言的长整数,事实上,Python 长整数仅受限于用户计算机的虚拟内存总数。如果你熟悉 Java, Python 的长整数类似于 Java 中的 BigInteger 类型。
True 会被当成整数值 1, 而 False则会被当成整数值 0
复数(包括-1 的平方根, 即所谓的虚数)在其它语言中通常不被直接支持(一般通过类来实现)。
decimal用于十进制浮点数。不是内建类型,需要导入decimal 模块,使用如字 1.1 无法用二进制浮点数精确表示
>>>1.1
1.1000000000000001
>>>print decimal.Decimal('1.1')
1.1
11、元组
可以看成是只读的列表。通过切片运算( [ ] 和 [ : ] )可以得到子集,这一点与字符串的使用方法一样。但切片得到的结果也是元组(不能被修改)
>>> aTuple = ('robots', 77, 93, 'try')
>>> aTuple
('robots', 77, 93, 'try')
>>> aTuple[:3]
('robots', 77, 93)
>>> aTuple[1] = 5
Traceback (innermost last):
File "<stdin>", line 1, in ?
TypeError: object doesn't support item assignment
12、循环中,for用法特殊
接受可迭代对象(例如序列或迭代器)作为其参数,每次迭代其中一个元素。如
for item in ['e-mail', 'net-surfing', 'homework','chat']:
print item
Python 提供了一个 range()内建函数来生成这种列表,满足for的需要,接受一个数值范围,生成一个列表:
>>>for eachNum in range(3):
print eachNum
也可以用len()配合for i in range(len(foo))
同时循环两个,enumerate()同时循环 索引和元素
for i, ch in enumerate(foo):
print ch, '(%d)' % i
13、列表解析
在一行中使用一个 for 循环将所有值放到一个列表当中
>>>squared = [x ** 2 for x in range(4)]
>>>for i in squared:
print i
输出结果:
0
1
4
9
更复杂如挑选出符合要求的值放入列表
sqdEvens = [x ** 2 for xin range(8) if not x % 2]
for i in sqdEvens:
print i
输出结果
0
4
16
36
14、列表、字符串、字典,自动对齐(统一用空格不容易出错)、if、while、文件的open()和file()功能简单,省略。
注意,file()内建函数,功能等同于 open(),这个名字可以更确切的表明它是一个工厂函数
15、属性
可以是简单的数据值,也可以是可执行对象,如函数和方法。
使用“.”访问对象属性,如object.attribute。
代码
filename = raw_input('Enter file name: ')
fobj = open(filename,'r')
for eachLine in fobj:
print eachLine,
fobj.close()
其中,使用逗号来抑制自动生成的换行符号。文件中的每行文本已经自带了换行字符, 如果我们不抑制 print 语句产生的换行符号, 文本在显示时就会有额外的空行产生。
但对于很大的文件来说, 上面的代码会占用太多的内存, 这时你最好一次读一行。
16、错误和异常
遇到错误抛出的信息,迅速定位问题并进行调试
代码添加错误检测及异常处理,封装在 try-except 语句当中。except 之后是处理错误的代码。可以用raise直接抛出一个异常。
try:
filename = raw_input('Enter file name: ')
fobj = open(filename, 'r')
for eachLine in fobj:
print eachLine, fobj.close()
except IOError, e:
print 'fileopen error:', e
17、类
class 关键字定义,提供一个可选的父类或者说基类; 如果没有合适的基类,
那就使用 object 作为基类。class 行之后是可选的文档字符串, 静态成员定义, 及方法定
义。
classFooClass(object):
"""my very first class: FooClass"""
version = 0.1 # class (data)attribute
def __init__(self, nm='John Doe'):
"""constructor"""
self.name = nm # class instance(data) attribute
print 'Created a class instance for', nm
defshowname(self):
"""display instance attribute and classname"""
print 'Yourname is', self.name
print 'My name is', self.__class__.__name__
defshowver(self):
"""display class(static) attribute"""
print self.version #references FooClass.version
defaddMe2Me(self, x): # does not use 'self'
"""apply + operation to argument"""
return x + x
其中定义了一个静态变量 version, 它将被所有实例及四个方法共享,__init__(), showname(), showver(), 及熟悉的addMe2Me(). 这些 show*()方法并没有做什么有用的事情,仅仅输出对应的信息。
__init__()方法,名字开始和结束都有两个下划线的方法都是特殊方法。这个方法用于类实例初始化时首先调用,类似构建函数。不过不象其它语言中的构建函数, 它并不创建实例--它仅仅是你的对象创建后执行的第一个方法。它的目的是执行一些该对象的必要的初始化工作。默认的__init__()方法什么都不做,可以覆盖重写。
每个方法都有的一个参数, self. 是类实例自身的引用。类似其他语言使用的this
18、模块导入用import
19、“PEP”(网站:http://python.org/dev/peps)
PEP就是一个 Python 增强提案(Python Enhancement Proposal), 这也是在新版Python 中增加新特性的方式。不但提供了新特性的完整描述, 还有添加这些新特性的理由,如果需要的话, 还会提供新的语法、 技术实现细节、向后兼容信息等等。
20、实用的内建函数
dir([obj]) 显示对象的属性,如果没有提供参数, 则显示全局变量的名字
type(obj) 返回对象的类型(返回值本身是一个 type 对象!)
int()
str()
help()
21、继续“\”
代码跨行写用反斜线 ( \ ),继续上一行
而分号 ( ; )将两个语句连接在一行中
22、缩进
使用四个空格宽度,避免使用制表符
23、赋值“=”
赋值并不是直接将一个值赋给一个变量,尽管其它语言编程如此。但Python中,对象是通过引用传递的。在赋值时,不管这个对象是新创建的,还是一个已经存在的,都是将该对象的引用(并不是值)赋值给变量。
c语言中,赋值语句其实是被当成一个表达式(可以返回值),但python中不行,Python 的赋值语句不会返回值,非法语句如
>>> x = 1
>>> y = (x = x + 1) # assignments not expressions! File"<stdin>", line 1
报错
y = (x = x + 1)
^
SyntaxError: invalid syntax
Python 不支持类似 x++ 或 --x 这样的前置/后置自增/自减运算
但支持增量赋值,运算符如下
+= -= *= /= %= **=
<<= >>= &= ^= |=
24、“多元”赋值
多个变量同时赋值,如x, y, z = 1, 2, 'a string'
交换两个变量值想x和y
x, y = 1, 2
x, y = y, x
25、python标示符:
关键字
专用下划线标识符
_xxx 不用'from module import *'导入
__xxx__系统定义名字
__xxx 类中的私有变量名
避免用下划线作为变量名的开始,下划线对解释器有特殊的意义。
变量名_xxx被看作是“私有的”,在模块或类外不可以使用。当变量是私有的时候,用_xxx 来表示变量是很好的习惯。因为变量名__xxx__对Python 来说有特殊含义。
26、文档
通过obj.__doc__动态获得文档字串。在模块,类声明,或函数声明中第一个没有赋值的字符串可以用属性 obj.__doc__来进行访问,其中 obj是一个模块,类,或函数的名字。
27、代码风格
模块结构和布局,推荐的标准风格,如下
使用main()函数,检查__name__ 变量的值
28、__name__ 指示模块应如何被加载
如果模块是被导入, __name__ 的值为模块名字
如果模块是被直接执行, __name__ 的值为 '__main__'
29、内存管理
变量无须事先声明
变量无须指定类型
程序员不用关心内存管理
变量名会被“回收”
del 语句能够直接释放资源
(1)动态类型
Python 语言中,对象的类型和内存占用都是运行时确定的。尽管代码被编译成字节码,Python 仍然是一种解释型语言。在创建事,也就是赋值时,解释器会根据语法和右侧的操作数来决定新对象的类型。
(2)内存分配
Python 解释器承担了内存管理的复杂任务,底层的事情放心交给 Python 解释器
30、引用计数
Python创建对象,是作为引用来使用(赋值的),创建时在申请一个内存空间,同时为这个内存空间生成一个 引用计数器,来记录该对象的引用传递给了多少对象(也是,多少新对象指向它)。所以,x=2,在python中先生成一个值为2的内存空间,并生成对应的引用计数器值为0,再将其的引用传给对象x,内存空间2的引用计数器加1(为1),x=y时,y同样指向内存空间2,其计数器继续加1(为0)。
书上说:Python 内部记录着所有使用中的对象各有多少引用。一个内部跟踪变量,称为一个引用计数器。当对象被创建时,就创建了一个引用计数,当不再需要时,引用计数变为0时,它被垃圾回收。
引用计数器增加情况
(1)对象被创建
x = 3.14
(2)或另外的别名被创建
y = x
(3)或被作为参数传递给函数(新的本地引用)
foobar(x)
(4)成为容器对象的一个元素
myList = [123, x, 'xyz']
引用计数器减少情况
(1)一个本地引用离开了其作用范围。如传入函数的fun(x),x在fun()结束后销毁,对应减1
(2)对象的别名被显式的销毁。
del y # or del x
(3)对象的一个别名被赋值给其它的对象
x = 123
(4)对象被从一个窗口对象中移除
myList.remove(x)
(5)窗口对象本身被销毁
del myList # or goes out-of-scope
31、垃圾收集
不再被使用的内存会被一种称为垃圾收集的机制释放。虽然解释器跟踪对象的引用计数,但垃圾收集器负责释放内存。垃圾收集器是一块独立代码,用来寻找引用计数为 0 的对象。虽然引用计数大于0但也应该被销毁的对象。 特定情形会导致循环引用。解释器会暂停下来, 试图清理所有未引用的循环。
32、使用局部变量替换模块变量
os.linesep字符串给出当前平台使用的行终止符。为os.linesep 属性取了一个新别名,这样做一方面可以缩短变量名, 另一方面也能改善访问该变量的性能。
Import os
ls =os.linesep
# write linesto file with proper line-ending
fobj =open(fname, 'w')
fobj.writelines(['%s%s'% (x, ls) for x in all])
fobj.close()
类似 os.linesep 这样的名字需要解释器做两次查询,模块内部函数需要解释器做两次查询,因为模块也是全局变量。这样做多耗费资源。
一个函数中类似这样频繁使用一个属性,我们建议你为该属性取一个本地变量别名。在查找全局变量之前, 总是先查找本地变量,经常用到的模块属性替换为一个本地引用。
33、一种新的 Python 结构, try-except-else 语句
try 子句是监测错误的代码块,
1 #!/usr/bin/env Python
2 # get filename
3 fname = raw_input('Enter filename: ')
4 try:
5 fobj= open(fname, 'r')
6 except IOError, e:
7 print"*** file open error:", e
8 else:
9 #display contents to the screen
10 foreachLine in fobj:
11 printeachLine,
12 fobj.close()
34、必须工具
Python 代码风格指南(PEP8), Python 快速参考和 Python 常见问答。
优秀的Python程序员必用一些模块:
Debugger: pdb
Logger: logging
Profilers: profile, hotshot, cProfile
调试模块 pdb 允许你设置(条件)断点,代码逐行执行,检查堆栈。它还支持事后调试。
logging 模块是在 Python2.3 中新增的, 它定义了一些函数和类帮助你的程序实现灵活的日志系统。共有五级日志级别: 紧急, 错误,警告,信息和调试。
性能测试模块
(1)pyhon profile 模块(Python 写成的,最老,最慢)
用来测试函数的执行时间,及每次脚本执行的总时间,既没有特定函数的执行时间也没有被包含的子函数调用时间
(2)hotshot 模块(C 语言写成,性能高)
python2.2中新增,目标是取代profile模块,修复profile模块的一些错误。
(3)hotshot模块
重点解决了性能测试过载的问题,但需要更多的时间来生成结果。Python2.5版修复一个关于时间计量的严重bug。
(4)cProfile 模块(C语言)
Python2.5新增,替换掉已经有历史的 hotshot 和 profile 模块。明显的缺点需要花较长时间从日志文件中载入分析结果, 不支持子函数状态细节及某些结果不准确。
Python 对像
1、三特性:身份,类型和值。
身份:每个对象唯一的身份标识,使用内建函数id()来得到,可以认为是对象的内存地址。不用关心。
类型:内建函数type()查看对象类型,返回值为对象非字符串。类型决定值、操作、规则,如
type(type(42))
<type 'type'>
值:对象数据项
特殊类型NoneType:只有一个值None,没有任何运算,没有任何内建方法。布尔值总是False。
2、内部类型
(1)代码: 编译的代码片段,可执行对象。通过调用内建函数 compile()可以得到代码对象。被exec 命令或 eval()内建函数来执行
(2)帧:执行栈帧,命令执行时的记录对象,包含 Python 解释器在运行时所需要知道的所有信息
(3)跟踪记录:报异常时创建追踪对象,保存栈追踪信息。当异常有自己的处理程序,则去访问这个跟踪记录的对象,执行处理异常。
(4)切片对象: Python 扩展的切片语法。sequence[start1 : end1, start2 :end2]. 也可以由内建函数 slice()来生成. 不同的索引切片操作,包括
步进切片:sequence[起始索引 : 结束索引 : 步进值],例子
>>> foolist = [123, 'xba', 342.23, 'abc']
>>> foolist[::-1]
['abc', 342.23, 'xba', 123]
多维切片:语法sequence[start1 : end1, start2 : end2],
省略切片:sequence[...,start1 : end1 ]
(5)省略 :用于扩展切片语法中,起记号作用。唯一的名字Ellipsis,布尔值始终为 True.
(6)Xrange :返回一个对象
3、标准类型运算符
(1)对象值的比较:可以连着
3 < 4 < 7 # same as ( 3 < 4 ) and ( 4 < 7 )
4 < 3 < 5 != 2 <7
不等于使用“!=”
对象间用is/is not 比较,如
b = 2.5e-5
a= b
a is b
返回结果为TRUE
(2)特殊的对象:
简单整数对象被缓存,多次赋值只用这一个对象。
整数对象和字符串对象是不可变对象,所以Python 会高效的缓存,造成我们认为Python应该创建新对象时,却没有创建新对象的假象。例子如下
>>> a = 1
>>> id(a)
8402824
>>> b = 1
>>> id(b)
8402824
>>>
>>> c = 1.0
>>> id(c)
8651220
>>> d = 1.0
>>> id(d)
8651204
其中,a 和 b 指向了相同的整数对象(地址一样),但是 c 和 d 并没有指向相同的浮点数对象(地址不同)。也就是说,Python 仅缓存简单整数(但这个功能不要使用),目前,简单整数的缓存范围是(-1, 100),不过这个范围是会改变的,所以请不要在你的应用程序使用这个特性。
另外,预定义缓存字符串表之外的字符串,不再有任何引用指向它,那这个字符串将不会被缓存。对象回收器一样可以回收不再被使用的字符串
4、标准类型内建函数
cmp(obj1,obj2) 比较 obj1 和 obj2, 根据比较结果返回整数 i:
i < 0 ifobj1 < obj2
i > 0 ifobj1 > obj2
i == 0 ifobj1 == obj2
repr(obj)或 `obj` 返回一个对象的字符串表示
str(obj) 返回对象适合可读性好的字符串表示
type(obj) 得到一个对象的类型,并返回相应的 type 对象
注意repr() 或反引号运算符“``”,以及str()三者完全一样,repr() 输出对 Python比较友好, 而str()的输出对人比较友好。
repr() 和 `` 做的是完全一样的事情,返回一个对象的“官方”字符串表示, 也就是说绝大多数情况下可以通过求值运算(使用 eval()内建函数)重新得到该对象,但 str()则有所不同。生成一个对象的可读性好的字符串表示,返回结果通常无法用于eval()求值, 但用于print语句输出。
5、内建函数isinstance()
比type()好一点,功能一样。因为提升性能方法:
(1)减少函数调用次数(尽量使用变量做比较项目)
(2)减少查询次数,from-import,你可以减少一次查询:
from typesimport IntType
if type(num)is IntType...
6、类型工厂函数
Python 2.2 统一了类型和类,所有内建类型也都是类。其内建转换函数如 int(), type(), list() 等等,都是类。看着像函数,实际是类。调用时也是生成实例。
7、标准类型的分类
“基本” ,是指这些类型都是 Python 提供的标准或核心类型。
“内建” ,是由于这些类型是 Python 默认就提供的
“数据” ,因为他们用于一般数据存储
“对象” ,因为对象是数据和功能的默认抽象
“原始” ,因为这些类型提供的是最底层的粒度数据存储
“类型” ,因为他们就是数据类型
8、存储模型
标量/原子类型 数值(所有的数值类型) ,字符串(全部是文字)
容器类型 列表、元组、字典
9、更新模型
可变类型 列表, 字典
不可变类型 数字、字符串、元组
10、不支持的类型
1,char 或 byte
如果要使用类似功能,可用长度为1的字符串,作为代替表示字符或 8 比特整数。
2,指针
内存地址python自动管理,不能手动管理,最多用id()函数得到对象身份号,类似但不是地址。Python中,一切都是指针。
3,整型不分int,short,long
Python的标准整型,融合了C中的长整型功能。而python的长整型(后边加L)是具有超级取值空间。如果两个很大的数相乘,Python会自动的返回一个长整数给你而不会报错。不像C。
4,Python 决定不支持单精度浮点数
Python中只有一种浮点数类型。但是对需要更高精确度而宁愿放弃更大的取值范围情况,Python 还有一种十进制浮点数类型Decimal,使用时需要decimal模块
数字对象
1、删除数字对象:用del
2、标准整数类型
Python 标准整数类型等价于C中(有符号)长整型。八进制整数以数字“0”开始,十六进制整数则以“0x” 或“0X” 开始
3、长整型
整数值后面加个 L(大写或小写都可以)。十进制,八进制,或十六进制都行。
C的长整型取值范围32位或64位。而python长整数不同,没有位数限制,能表达的值仅仅与机器的(虚拟)内存大小有关,范围很大,可以表达超级整数。
注意:
python中,整型计算多大会自动转换成长整型,所以
python不存在整数超范围的错误,只会给个warning,如
2 << 32
给出信息:__main__:1: FutureWarning: x<<ylosing bits or changing sign will return a long in Python 2.4 and up
4、双精度
。 每个浮点数占8个字节 (64比特) , 完全遵守IEEE754号规范 (52M/11E/1S) , 其中 52 个比特用于表示底,11 个比特用于表示指数(可表示的范围大约是正负 10 的 308.25次方) , 剩下的一个比特表示符号。但实际精度依赖于机器架构和创建 Python 解释器的编译器。
5、复数处理
6、混合模式运算符
“+”对不用类型不同操作,不仅是加法
整数转换为浮点数, 非复数转换为复数。Python 提供了coerce()内建函数来帮助你实现这种转换。
7、地板除
1 // 2 #floors result, returns integer # 地板除, 返回整数
0
>>>1.0 // 2.0 # floors result, returns float # 地板除, 返回浮点数
0.0
expr1 //expr2 表达式1 地板除以 表达式2
expr1 %expr2 表达式1 对表达式2 取
>>>-1 // 2 # move left on number line# 返回比 –0.5小的整数,也就是-1
8、幂运算“**”
另外,python的位运算支持整数:
取反(~),按位 与(&),或(|)及 异或(^)及左移(<<)和右移(>>)只支持整数。
9、功能函数
五个数值运算内建函数:
abs(num) 返回 num 的绝对值
coerce(num1, num2) 将num1和num2转换为同一类型,然后以一个元组的形式返回。
divmod(num1,num2) 除法-取余运算的结合。返回一个元组(num1/num2,num1%num2)。对浮点数和复数的商进行下舍入(复数仅取实数部分的商)
pow(num1, num2, mod=1) 取 num1 的 num2次方,如果提供 mod参数,则计算结果再对mod进行取余运算
round(flt, ndig=0) 接受一个浮点数flt并对其四舍五入,保存ndig位小数。若不提供ndig参数,则默认小数点后0位。
round()仅用于浮点数。(译者注:整数也可以,不过并没有什么实际意义)
其中,coerce(),返回一个类型转换后的包含两个数值元素的元组。是不依赖 Python解释器的数据类型转换函数,如
>>>coerce(1, 2)
(1, 2)
>>>coerce(1.3, 134L)
(1.3, 134.0)
>>>coerce(1j, 134L)
(1j,(134+0j))
>>>coerce(1.23-41j, 134L)
((1.23-41j),(134+0j))
divmod()内建函数把除法和取余运算结合起来, 返回一个包含商和余数的元组
>>> divmod(10,3)
(3, 1)
函数pow() 是指数运算,功能和双星号 (**)一样,但pow(x,y,z)有第三个可选的参数,叫余数参数。pow() 先进行指数运算,然后将运算结果和第三个参数进行取余运算。这个特性主要用于密码运算,并且比 pow(x,y) % z 性能更好
10、仅用于整数的函数
(1)进制转换函数oct() 和 hex()
>>>hex(23094823l)
'0x1606627L'
>>>hex(65535*2)
'0x1fffe'
>>>
>>>oct(255)
'0377'
>>>oct(23094823l)
'0130063047L'
>>>oct(65535*2)
'0377776'
(2)ASCII 转换函数ord()和chr()
ord('a')
97
>>>ord('A')
65
>>>chr(97)
'a'
>>>chr(65L)
'A'
另外,注意
chr(num) 将ASCII值的数字转换成ASCII字符,范围只能是0<=num <=255
ord(chr) 接受一个ASCII或Unicode字符(长度为1的字符串),返回相应的ASCII或Unicode值
unichr(num) 接受Unicode码值,返回其对应的Unicode字符。所接受的码值范围依赖于Python是构建于UCS‐2还是UCS‐4
11、十进制浮点数
天生缺憾的表达,如
>>> 0.1
0.1000000000000001
这些片断不停的重复直到舍入出错。所以针对数据类型,使用对应的类型
decimal 十进制浮点运算类Decimal
array 高效数值数组(字符,整数,浮点数等等)
math/cmath 标准C库数学运算函数。 常规数学运算在match模块,
复数运算在cmath模块
Operator 数字运算符的函数实现。比如 tor.sub(m,n)等价于m - n
random 多种伪随机数生成器
这些片断不停的重复直到舍入出错
高级的数字科学计算应用的著名的第三方包 Numeric(NumPy) 和 SciPy:
http://numeric.scipy.org/
http://scipy.org/
12、随机数
randint()两个整数参数,返回二者之间的随机整数
randrange() 它接受和 range()函数一样的参数, 随机返回
range([start,]stop[,step])结果的一项
uniform() 几乎和 randint()一样,不过它返回的是二者之间的一个浮点数(不包括范围上限)。
random() 类似 uniform() 只不过下限恒等于 0.0,上限恒等于1.0
choice() 随机返回给定序列(关于序列,见第六章)的一个元素
序列、字符串、列表、元组
1、序列操作符
seq[ind] 获得下标为 ind 的元素
seq[ind1:ind2]获得下标从 ind1 到 ind2 间的元素集合
seq *expr 序列重复 expr 次
seq1 +seq2 连接序列 seq1 和 seq2
obj inseq 判断 obj 元素是否包含在 seq 中
obj not inseq 判断 obj 元素是否不包含在 seq 中
切片有很多小技巧,自己查,如
s[::-1] # 可以视作"翻转"操作
s[::2] # 隔一个取一个的操作
2、序列的内建函数(BIFs)
序列本身内含迭代的概念,是简单的迭代器。
(1)各类型之间的转换:转换实际上是工厂函数,将参数的内容(浅)拷贝到新生成对象
list(iter) 把可迭代对象转换为列表
str(obj) 把 obj 对象转换成字符串(对象的字符串表示法)
unicode(obj) 把对象转换成 Unicode 字符串(使用默认编码)
basestring() 抽象工厂函数,其作用仅仅是为 str 和 unicode 函数提供父类,所以不能被实例化,也不能被调用
tuple(iter) 把一个可迭代对象转换成一个元组对象
其中,建立python后不能更改其身份或类型。建立一个浅拷贝,只拷贝了对象的索引,而不是重新建立了一个对象。
3、其他内建函数
注意,len(),reversed()和sum()函数只能接受序列类型对象作为参数,而剩下的则还可以接受可迭代对象做为参数,另外,max()和 min()函数也可以接受一个参数列表,如下
enumerate(iter) 接受一个可迭代对象作为参数,返回一个 enumerate 对象(同时也是一个迭代器),该对象生成由 iter 每个元素的 index 值和 item 值组成的元组(PEP 279)
len(seq) 返回 seq 的长度
max(iter,key=None) ormax(arg0,arg1...,key=None) 返回iter或(arg0,arg1,...)中的最大值, 如果指定了key, 这个key必须是一个可以传给sort()方法的,用于比较的回调函数
min(iter, key=None) or min(arg0,arg1.... key=None) 返回 iter 里面的最小值;或者返回(arg0,arg2,...)里面的最小值;如果指定了 key,这个 key 必须是一个可以传给sort()方法的,用于比较的回调函数.
reversed(seq) 接受一个序列作为参数,返回一个以逆序访问的迭代器(PEP 322)
sorted(iter,func=None,key=None,reverse=False) 接受一个可迭代对象作为参数,返回一个有序的列表;可选参数func,key 和 reverse 的含义跟 list.sort()内建函数的参数含义一样
sum(seq, init=0) 返回 seq 和可选参数 init 的总和,其效果等同于reduce(operator.add,seq,init)
zip([it0, it1,... itN]) 返回一个列表,其第一个元素是 it0,it1,...这些元素的第一个元素组成的一个元组,第二个...,类推.
特殊的序列:字符串的切片操作
成员操作符(in ,not in) 判断一个字符或者一个子串(中的字符)是否出现在另一个字符串中。出现则返回 True,否则返回 False
判断一个字符串是否包含另一个字符串的find()或者index(),还有rfind()和rindex())函数来完成
>>>'bc' in 'abcd' True
>>>'n' in 'abcd' False
>>>'nm' not in 'abcd' True
string 模块预定义的字符串:
>>import string
>>>string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>>string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'
>>>string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>>string.digits
'0123456789'
所以,可以简单的写一个检查小脚本,标识符检查idcheck.py
#Python 标识符必须以字母或下划线开头,后面跟字母,下划线或者数字
import string
alphas = string.letters + '_'
nums = string.digits
print 'Welcome to the IdentifierChecker v1.0'
print 'Testees must be at least 2chars long.'
inp = raw_input('Identifier to test?')
if len(myInput) > 1:
if myInput[0] not in alphas:
print'''invalid: first symbol must be alphabetic'''
else:
for otherChar inmyInput[1:]:
if otherChar not inalphas + nums:
print '''invalid:remaining symbols must be alphanumeric'''
break
else:
print "okay as anidentifier"
4、性能提升:(计算尽量不重复,提前算好成变量,)
性能的的角度,把重复操作作为参数放到循环里面进行是非常低效的,如
while i < len(myString):
print 'character %d is:', myString[i]
其中,len(myString)每次都被计算,浪费资源,改成
length = len(myString)
while i < length:
5、字符串分行写,不用加反斜杠“/”也自动拼成一行
6、格式字符串
%c 转换成字符(ASCII 码值,或者长度为一的字符串)
%r 优先用 repr()函数进行字符串转换
%s 优先用 str()函数进行字符串转换
%d/%i 转成有符号十进制数
%u 转成无符号十进制数
%o 转成无符号八进制数
%x/%X (Unsigned)转成无符号十六进制数(x/X代表转换后的十六进制字符的大小写)
%e/%E 转成科学计数法(e/E 控制输出 e/E)
%f/%F 转成浮点数(小数部分自然截断)
%g/%G %e 和%f/%E 和%F 的简写
%% 输出%
辅助的字符串格式化符号
* 定义宽度或者小数点精度
- 用做左对齐
+ 在正数前面显示加号( + )
<sp> 在正数前面显示空格
# 在八进制数前面显示零('0'),在十六进制前面显示'0x'或者'0X'(取决于用的是'x'还是'X')
0 显示的数字前面填充‘0’而不是默认的空格
% '%%'输出一个单一的'%'
(var) 映射变量(字典参数)
m.n m 是显示的最小总宽度,n 是小数点后的位数(如果可用的话)
举几个例子
>>>"%#X" % 108
'0X6C'
>>>
>>>"%#x" % 108
'0x6c'
>>>'%.2f' % 1234.567890
'1234.57'
>>>'%E' % 1234.567890
'1.234568E+03'
>>>'%e' % 1234.567890
'1.234568e+03'
>>>'%g' % 1234.567890
'1234.57'
>>>'%G' % 1234.567890
'1234.57'
>>>"%e" % (1111111111111111111111L)
'1.111111e+21'
>>>"%+d" % 4
'+4'
>>>"%+d" % -4
'-4'
新式的字符串模板
官网:https://docs.python.org/2/library/string.html
特殊讲解:http://jianpx.iteye.com/blog/899230
优势是不用记所有细节,而如shell风格那样使用美元符号($).由于新式的字符串 Template 对象的引进使得 string 模块又重新活了过来,Template 对象有两个方法,substitute()和safe_substitute(),如
>>> from string importTemplate
>>> s = Template('There are${howmany} ${lang} Quotation Symbols')
>>> prints.substitute(lang='Python', howmany=3)
结果There are 3 Python Quotation Symbols
7、zip()
>>>s, t = 'foa', 'obr'
>>>zip(s, t)
[('f', 'o'),('o', 'b'), ('a', 'r')]
8、str() and unicode()
str()和 unicode()函数都是工厂函数,就是说产生所对应的类型的对象,它们和basestring都可以作为参数传给isinstance()函数来判断一个对象的类型
>>>isinstance(u'\0xAB', str)
False
>>>not isinstance('foo', unicode)
True
>>>isinstance(u'', basestring)
True
>>>not isinstance('foo', basestring)
False
9、Unicode
字符串前加u表示编码成Unicode字符串,如,如u’sdfad’是Unicode字符串。
Unicode是编码方式,用于计算机支持都语言的。ASCII编码方式中每个英文字符以七位二进制数的方式存贮在计算机内,其范围是 32 到 126,目前8为可以表示128种。
codec是COder/DECoder的首字母组合,定义了文本跟二进制值的转换方式。ASCII用一个字节把字符转换成数字。而nicode用的是多字节,支持多种编码,常用的四种ASCII,ISO 8859-1/Latin-1,UTF-8 和 UTF-16。
UTF-8 编码跟 ASCII 编码完全相同。用1个到4个字节来表示其他语言的字符,CJK/East这样的东亚文字一般都是用 3 个字节来表示,那些少用的、特殊的、或者历史遗留的字符用 4 个字节来表示。Python内部自动完成UTF-8读写工作,不需要关心,免去了直接处理Unicode 数据时处理多字节字符的复杂问题。
代码如下:
CODEC = 'utf-8'
hello_out = u"Hello world\n"
bytes_out = hello_out.encode(CODEC)
hello_in = bytes_in.decode(CODEC)
print bytes_out, hello_in
UTF-16用16位、两个字节来存储字符,易读写。但顺序需要定义一下,一般UTF-16编码文件都需要一个BOM(Byte Order Mark),或者你显式地定义UTF-16-LE(小端)或者 UTF-16-BE(大端)字节序。UTF-16 是一种变长编码,不常用,因为不兼容包ASCII,而且一般不会知道或者根本不在意除了基本多文种平面 BMP 之外到底使用的是那种平面,
10、Python的Unicode 应用
Python 标准库里面的绝大部分模块都是兼容 Unicode 的。但pickle 模块只支持 ASCII 字符串。如果你把一个 Unicode 字符串交给 pickle 模块来 unpickle,它会报异常.你必须先把你的字符串转换成 ASCII 字符串才可以.所以最好是避免基于文本的 pickle 操作.幸运地是现在二进制格式已经作为 pickle 的默认格式了,pickle 的二进制格式支持不错.这点在你向数据库里面存东西是尤为突出,把它们作为BLOB字段存储而不是作为TEXT或者VARCHAR字段存储要好很多.万一有人把你的字段改成了
Unicode 类型,这可以避免 pickle 的崩溃.
另外,使用第三方模块时要注意Unicode通讯方面遇到麻烦,要设置好环境中相应的参数设置
11、Python 的 Unicode 支持(P203)
12、RE 引擎对Unicode的支持
正则表达式引擎需要 Unicode 支持.详见 6.9 节的 re 模块
常用 Unicode 编辑码
编码 描述
utf-8 变量长度为 8 的编码(默认编码)
utf-16 变量长度为 16 的编码(大/小端)
utf-16-le 小端 UTF-16 编码
utf-16-be 大端 UTF-16 编码
ascii 7-bit 7 位 ASCII 码表
iso-8859-1 ISO 8859-1 (Latin-1) 码表
unicode-escape(定义见 Python Unicode 构造函数)
raw-unicode-escape(定义见 Python Unicode 构造函数)
native Python 用的内部格式
13、与字符串类型有关的模块
模块 描述
string 字符串操作相关函数和工具,
re 正则表达式:强大的字符串模式
struct 字符串和二进制之间的转换
c/StringIO 字符串缓冲对象,操作方法类
base64 Base 16,32,64 数据编解码
codecs 解码器注册和基类
crypt 进行单方面加密
diffliba 找出序列间的不同
hashlib 多种不同安全哈希算法和信息摘要
hma HMAC 信息鉴权算法的 Python
md5 RSA 的 MD5 信息摘要鉴权
rotor 提供多平台的加解密服务
sha NIAT 的安全哈希算法 SHA
stringprep 提供用于 IP 协议的 Unicode 字符串
textwrape 文本打包和填充
unicodedata Unicode数据库
14、Python 字符串不是通过 NUL 或者'\0'来结束的
不需要像C一样添加结束符,python自动管理,字符串中只包含你所定义的东西,没有别的。
15、
16、列表类型内建函数
Python 中没有特定用于列表的内建函数。只有range()函数接受一个数值作为输入,输出一个符合标准的列表.
列表类型支持的所有方法:
list.append(obj) 向列表中添加一个对象obj
list.count(obj) 返回一个对象obj 在列表中出现的次数
list.extend(seq) 把序列seq 的内容添加到列表中
list.index(obj, i=0, j=len(list)) 返回 list[k] == obj 的 k 值,并且 k 的范围在i<=k<j;否则
引发ValueError 异常.
list.insert(index, obj) 在索引量为 index 的位置插入对象 obj.
list.pop(index=-1) 删除并返回指定位置的对象,默认是最后一个对象
list.remove(obj) 从列表中删除对象obj
list.reverse() 原地翻转列表
list.sort(func=None,key=None, reverse=False) 以指定的方式排序列表中的成员,如果 func 和 key 参数指定,则按照指定的方式比较各个元素,如果reverse 标志被置为True,则列表以反序排列.
17、可以改变对象值的可变对象的方法是没有返回值的
python方法不一定有返回值,如sort(),extend()和 reverse()这些操作在列表中原地执行操作,原列表内容被改变,没有返回值。与之相反,字符串不能被改变,所以这些函数产生新对象,一定会有返回值。
18、元组的特殊特性
元组也没有它自己专用的运算符和内建函数,因为元组是不可变的,没有实现排序,替换,添加等方法
但元组也可以间接的变化,如两个元组用加号+连接;或者元组元素为列表,就可以增减元素。
19、所有函数返回的多对象(不包括有符号封装的)都是元组类型。
注意,有符号封装的多对象集合其实是返回的一个单一的容器对象,如
def foo1():
:
return obj1,obj2, obj3 #等同于return (obj1, obj2, obj3)
20、单元素元组声明为 ('xyz',)
('xyz') #直接声明是字符串,不是元组,必须加“,”
'xyz'
>>> type(('xyz')) # astring, not a tuple
<type 'str'>
21、与序列类型相关的模块
数组 一种受限制的可变序列类型,要求所有的元素必须都是相同的类型
copy 提供浅拷贝和深拷贝的能力
operator 包含函数调用形式的序列操作符,比如 operator.concat(m,n)就相当于连接操作(m+n)。
re Perl 风格的正则表达式查找(和匹配);见第 15 章
StringIO/cStringIO 把长字符串作为文件来操作,比如 read(),seek()函数等,C 版的更快一些,但是它不能被继承.
Textwrap 用作包裹/填充文本的函数,也有一个类
types 包含 Python 支持的所有类型
collections 高性能容器数据类型
22、python的浅拷贝与深拷贝
http://greybeard.iteye.com/blog/1442259
http://www.cnblogs.com/BeginMan/p/3197649.html
copy 模块中只有两个函数可用:
(1) copy()进行浅拷贝操作
(2) deepcopy()进行深拷贝操作
浅拷贝:没有申请新内存,新指针(地址)与原指针都指向一个内存,原来对象的内存。
也就是说,新创建了一个类型跟原对象一样,其内容是原来对象元素的引用,换句话说,这个拷贝的对象本身是新的,但是它的内容不是.
序列类型对象默认拷贝是浅拷贝,主要有以下几种方式实施:
(1)完全切片操作[:],
(2)利用工厂函数,比如 list(),dict()等
(3)使用 copy 模块的 copy 函数
深拷贝:又叫完全拷贝。新申请内存,新指针(地址)指向新内存,新对象完全独立于老对象。
注意:
第一,非容器类型没有被拷贝一说,如数字,字符串和其他"原子"类型的对象,像代码,类型和 xrange 对象等,而浅拷贝是用完全切片操作来完成的
第二,如果元组变量只包含原子类型对象,那么深拷贝也相当于浅拷贝.因为内部是非容器类对象,python缓存了对象,所以只有一个内存空间。
如,我们把账户信息改成元组类型,那么即便按我们的要求使用深拷贝操作也只能得到一个浅拷贝:
>>>person = ['name', ('savings', 100.00)]
>>>newPerson = copy.deepcopy(person)
>>>[id(x) for x in person, newPerson]
[12225352,12226112]
>>>[id(x) for x in person]
[9919616,11800088]
>>>[id(x) for x in newPerson]
[9919616,11800088]
总之,
a.只有容器类才有拷贝概念,分深拷贝和浅拷贝;
b.非容器类不分,都是python缓存对象共享一个地址如字符串、数字;
c.复合容器(如list元素是元组,而元组的元素是list)的copy,其外部和内部对象分别对应自身对象的copy机制,外部list自身可以是深拷贝,但内部元组元素共享缓存独享(类似浅拷贝)、而外部元组类似浅拷贝时,内部list对象元素是深拷贝,代码如下:
importcopy
tuple1= ([1,2,3],'a','b')
tuple3= tuple1 #浅拷贝
tuple4= copy.deepcopy(tuple1)#深拷贝
print[id(x)
for x intuple1]
print[id(x)
for x intuple3]
print [id(x) for xin tuple4]
输出结果为:
[40129800L, 38969632L, 39037848L]
[40129800L, 38969632L, 39037848L]
[40558664L,38969632L, 39037848L]
23、string、tuple、list的built-in函数
三者都支持的共享函数:
cmp()
len()
list()
max()
min()
[:] slice切片符号
*
+
In
not in
只有string和list共同支持的函数:
count()
index()
. attributes属性提取符号
另外,insert()、append()、extend()三者只有list支持。三者都是添加操作,前两个是添加单个元素,extend()是添加另一个list对象,相当于 “+”操作符功能。
剩下的其他内建函数只有string支持,如zfill()、upper()、%、ord()、oct()、hex()、find()、expandtabs()、cpitalize()、center()、chr()、decode()、encode()、endswith()等等。
字典
1、字典的创建
dict1 = {}
dict2 = {'name': 'earth','port': 80}
dict3 = dict((['x', 1],['y', 2]))
注意用dict方法建立字典对象,可用于对象间的转化,转化list对象,然后转化为字典。
内建方法fromkeys()创建元素具有相同的值的字典(未给出,默认为 None):
>>> ddict = {}.fromkeys(('x', 'y'), -1)
>>> ddict
{'y': -1, 'x': -1}
>>> edict = {}.fromkeys(('foo', 'bar'))
>>> edict
{'foo': None, 'bar': None}
2、循环访问字典
for key indict2.keys():
... print'key=%s, value=%s' % (key, dict2[key])
或者简化直接用字典名
for key indict2:
... print'key=%s, value=%s' % (key, dict2[key])
3、判断元素村子尽量使用in和not in,不用has_key()
'name' in dict2
4、删除字典元素和字典
deldict2['name'] # 删除键为“name”的条目
dict2.clear() # 删除 dict2 中所有的条目
deldict2 # 删除整个 dict2 字典
dict2.pop('name')# 删除并返回键为“name”的条目
5、请不要用内建类型为变量命名,如dict, list, file, bool, str, input,len
6、字典比较
先长度,然后逐个元素,先比较key,在比较value,谁大立刻返回1、0、-1
7、hash()
返回参数对象的哈希值。不是为字典设计的方法,可以判断某个对象是否可以做一个字典的键。
集合
Set内部元素无序,所以不可以为集合创建索引或执行切片(slice)操作,也没有键(keys)可用来获取集合中元素的值。
两种集合
可变集合(set) :可添加删除元素
不可变集合(frozenset):不可以添加删除元素
创建集合方法
工厂方法 set() 和 frozenset():
参数必须是可迭代的,即,一个序列,或迭代器,或支持迭代的一个对象,例如:一个文件或一个字典
>>> s = set('cheeseshop')
>>> s
set(['c', 'e', 'h', 'o', 'p', 's'])
>>> t = frozenset('bookshop')
>>> t
frozenset(['b', 'h', 'k', 'o', 'p', 's'])
>>> type(s)
<type 'set'>
>>> type(t)
<type 'frozenset'>
作用函数len()、==、in、not in:
例如: for i in s:
... print i
添加、删除元素:
>> s.add('z')
>>> s
set(['c', 'e', 'h', 'o', 'p', 's', 'z'])
>>> s.update('pypi')
>>> s
set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y', 'z'])
>>> s.remove('z')
>>> s
set(['c', 'e', 'i', 'h', 'o', 'p', 's', 'y'])
>>> s -= set('pypi')
>>> s
set(['c', 'e', 'h', 'o','s'])
不可变集合不能添加、删除元素,会报错
t.add('z')
Traceback (most recent call last):
File "<stdin>",line 1, in ?
AttributeError: 'frozenset' object has no attribute 'add'
删除:del s
集合的比较
是判断两集合是超集或子集。只跟集合中元素组成有关,与元素顺序、集合长度等其他无关
“小于” 符号( <, <= )用来判断子集;
“大于”符号( >, >= )用来判断超集。
>>>set('shop') < set('cheeseshop')
True
>>>set('bookshop') >= set('shop')
True
集合类型操作符
条件和循环
Else用在循环中
在 while 和 for 循环中使用else语句,else子句在循环完成后,最后执行, 如果有break语句则会跳过else块。
迭代器和iter() 函数
迭代器一组数据结构,利用引从0开始一直"迭代"到序列的最后一个条目。支持多种对象,如字典,类对象。提升性能。
迭代通过对象的next()方法,而不是通过索引来计数,迭代全部完成后发出StopIteration异常作为结束标志,不是报错。代码如下
fetch = iter(seq)
while True:
try:
i = fetch.next()
except StopIteration:
break
do_something_to(i)
文件迭代
用reachLine in myFile或者foreachLine in myFile.readlines()都可以。如
myFile =open('config-win.txt')
for eachLinein myFile:
... print eachLine, # comma suppresses extra\n
列表解析
List comprehensions, 或缩略为listcomps,简单实用的工具,用来动态地创建列表。
语法:expr for iter_var initerable
其中,expr是一个表达式,完成计算。
列表解析的表达式可以取代内建函数,而且效率更高。如map()、lambda、filter()等,被简化为一个列表解析式,函数功能:
map() 对所有的列表成员应用一个操作
filter() 基于一个条件表达式过滤列表成员
lambda 允许你快速地创建只有一行的函数对象
例子:
map(lambda x:x ** 2, range(6))
可以简化为:[x** 2 for x in range(6)]
扩展语法:
[expr foriter_var in iterable if cond_expr]
例子,判断奇数:
>>> seq = [11, 10, 9, 9,10, 10, 9, 8, 23, 9, 7, 18, 12, 11, 12]
>>> filter(lambda x: x %2, seq)
[11, 9, 9, 9, 23, 9, 7, 11]
用列表解析:
>>> [x for x in seq if x% 2]
[11, 9, 9, 9, 23, 9, 7, 11]
三行五列的矩阵
>>> [(x+1,y+1) for x inrange(3) for y in range(5)]
[(1,1),(1,2),(1, 3),(1,4),(1,5),(2,1),(2,2),(2,3),(2,4),(2,5),(3,1),(3,2),(3,3),(3,4),(3,5)]
计算出所有非空白字符的数目,把每行分割(split )为单词
>>> f = open('hhga.txt','r')
>>> len([word for linein f for word in line.split()])
计算文件大小
importos
>>>os.stat('hhga.txt').st_size
499L
列表解析统计非空字符(去空格)为
>>>f.seek(0)
>>>sum([len(word) for line in f for word in line.split()])
408
处理大文件时readlines()会读取文件的所有行,用迭代器,生成器表达式替换列表解析,比如用max() 内建函数得到最长的字符串长度:
f =open('/etc/motd', 'r')
allLineLens= [len(x.strip()) for x in f]
f.close()
returnmax(allLineLens)
用生成器表达式简化,移到max()中
f =open('/etc/motd', 'r')
longest= max(len(x.strip()) for x in f)
f.close()
returnlongest
文件对象
文件只是连续的字节序列. 数据的传输经常会用到字节流, 无论字节流是由单个字节还是大块数据组成.
文件打开
open()和file()一样,可相互替换。
出错产生IOError 异常
建议使用open()读写文件, 在在处理文件对象时使用file(),例如 ifinstance(f, file) .
输出方法
write() 或 writelines()不会自动加入行结束符。因为read的时候不删除,所以自带。如没有必须自己加上。
文件内移动
seek() 方法,参数offset
默认值为0代表文件开头
1 代表从当前位置算起,
2 代表从文件末尾算起
text()返回前文件指针在文件中的位置。从文件起始算起,单位为字节。
目前python读取文件的高效方法
目前,使用文件迭代是最高效的方法,直接
for eachLinein f:
而老的方法file.xreadlines()最高效。
最差file.readlines()会一次读入所有行到一个列表,需要大内存。内存不足时,用readline()一次读入一行,但效率非常慢。遇到foreachLine in f.readline(),全部修改成文件迭代方式。
文件对象的一些内建方法
file.fileno() 返回文件的描述符(filedescriptor ,FD, 整数
file.flush() 刷新文件的内部缓冲区
file.isatty() 判断 file 是否是一个类tty 设备
file.next () 返回文件的下一行(类似于file.readline() ), 或在没有其它行时引发StopIteration 异常
file.seek(off, whence=0) 在文件中移动文件指针, 从 whence ( 0 代表文件其始, 1 代
表当前位置,2 代表文件末尾)偏移 off 字节
file.tell() 返回当前在文件中的位置
file.truncate(size=file.tell()) 截取文件到最大 size 字节, 默认为当前文件位置
文件内建属性
file.closed True表示文件已经被关闭,否则为False
file.encoding 文件所使用的编码- 当Unicode 字符串被写入数据时,它们将自动使用file.encoding 转换为字节字符串;若file.encoding为 None 时使
用系统默认编码
file.mode 文件打开时使用的访问模式
file.name 文件名
file.newlinesa未读取到行分隔符时为None, 只有一种行分隔符时为一个字符串, 当文件有多种类型的行结束符时,则为一个包含所有当前所遇到的行结束符的列表
file.softspace 为 0 表示在输出一数据后,要加上一个空格符,1 表示不加。这个属性
标准文件
程序一执行, 那么你就可以访问三个标准文件。分别是标准输入(一般是键盘), 标准输出(到显示器的缓冲输出)和标准错误(到屏幕的非缓冲输出),对应为stdin, stdout 和stderr。
函数
1、装饰器
(将多个函数的相同功能代码提取成一个装饰函数,用@+函数名放在函数前直接调用,实际是将被装饰函数作为参数传入装饰函数中,返回新的参数对象,原有被装饰函数对象作废)
http://blog.csdn.net/thy38/article/details/4471421
http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html列举多种情况的使用方法,说明每种结果。
类似于Java的AOP(Aspect Oriented Programming,面向方面编程)
一个用来包装函数的函数,返回一个修改之后的函数对象,将其重新赋值原来的标识符,并永久丧失对原始函数对象的访问。
用途 :
引入日志、
增加计时逻辑来检测性能、
给函数增加事务的能力。
简单说,为已经存在的对象添加额外的功能。在函数执行前和执行后分别附加额外功能。
也就是,装饰函数的参数是被装饰的函数对象,返回原函数对象,实际上为myfunc= deco(myfunc),比如下面代码
[python] view
plaincopy
1. def deco(func):
2. print func
3. return func
4. @deco
5. def foo():pass
6. foo()
实际代码是foo=deco(foo)
普通装饰器,就是定义一个装饰函数名,以作用函数(需要包装的函数)为参数,内部定义封闭函数,也就是返回定义函数对,代码如下,看最后一行,返回内部封闭函数对象:
def decorator(F):
def new_F(a, b):
print("input", a, b)
return F(a, b)
return new_F
具体见http://www.cnblogs.com/vamei/archive/2013/02/16/2820212.html
如果装饰函数需要参数,而被装饰函数也有参数,就做三层包装:
# a new wrapper layer
def pre_str(pre=''):
# old decorator
def decorator(F):
def new_F(a, b):
print(pre + "input", a, b)
return F(a, b)
return new_F
return decorator
# get square sum
@pre_str('^_^')
def square_sum(a, b):
return a**2 + b**2
参数'^_^'是装饰函数的参数,F是被装饰函数名,而内部是包装的执行函数。也就是说有参数传入加一层。
3.闭包
在函数内部定义一个内部函数(嵌套函数),其引用了外部作用域的变量,并且不是全局变量,那么这个内部函数叫闭包。装饰器就是闭包。
3.递归
函数调用自身叫递归,典型例子,阶乘factorial(N)= N* factorial(N-1),求N项值需要知道N-1项值。
4.生成器
生成器是带yield语句的函数:
(其实生成器对象就是有next()函数,每次调用直接返回yield后面的对象,也就是说yield是next()函数的返回标志,简单用途如每次返回列表第一个位置的元素)
能暂停执行并返回一个中间的结果(yield语句部分的功能:返回一个值给调用者并暂停执行),当调用next()方法时,会准确地从离开地方继续执行(当它将返回值和控制传递给调用者时)。而普通函数或者子程序只返回一次。
从_future_模块中导入generators来用生成器,从2.3开始直接用。
简单的生成器:
defsimpleGen():
yield 1
yield '2 --> punch!'
调用方法和执行结果:
myG = simpleGen()
myG.next()
输出:1
myG.next()
输出:'2--> punch!'
myG.next()
输出:Traceback(most recent call last):
File "", line 1, in ? myG.next() StopIteration
遇到next()没有值可返回,就抛出异常StopIteration。
模块
Python的下划线用法
(1)在交互式解释器会话中,“_”代表上一条执行的语句的结果。
(2)“_”作为临时性的名称使用,就是不会在后面再次用到该名称,而临时分配了一个特定的名称。如
n = 42
for _ in range(n):
do_something()
(3)“_”作为一个函数来使用,如Django文档“转换”章节中的代码。这样用法易冲突,尽量不用。
(4)在程序代码中用法三种:
_xxx 不能用'from module import *'导入
__xxx__ 系统定义名字(程序员自己不要这样命名)
__xxx 类中的私有变量名(自动进行私有转换Private name mangling)
核心风格:避免用下划线作为变量名的开头。其他下划线用法都是为了避免命名重复。具体解释如下:
名称前的单下划线,类似一种惯例,指定该属性为“私有”,只供内部使用。
“from<模块/包名>import *”,那么以“_”开头的名称都不会被导入,除非模块或包中的“__all__”(指定可以导入的对象列表,不在表中不导入,被屏蔽)列表显式地包含了它们。了解更多请查看Importing * in Python。但用import导入整体模块,每个对象都可以访问了。
名称前的双下划线(如:__shahriar)为了避免与子类定义的名称冲突,私有变量 名字改编(Privatename
mangling),即在代码生成之前被转换为长格式(变为公有),也就是变量前端加上下划线字符和类名“_类名”。代码实例如,有类A,
>>>class A(object):
... def _internal_use(self):
... pass
... def __method_name(self):
... pass
...
>>>dir(A())
['_A__method_name',..., '_internal_use']
在设计继承类B:
>>>class B(A):
... def __method_name(self):
... pass
...
>>>dir(B())
['_A__method_name','_B__method_name', ..., '_internal_use']
循环导入
a.py导入了模块b.py,而修改b.py的过程中添加导入模块a.py,就会报错,这是循环导入错误。
Import都是在a.py和b.py的文件开头。
解决办法有两个:
1,移除一个导入语句
2,将b.py的import语句放入函数内部。不要放在开头。
类
封装:数据属性对外隐藏,自身设计访问方法供外部使用
合成:将多个类合成一个类
泛化:提取共性做成父类
特化:设计新功能的子类
多态:调用不同对象的相同名称的函数,却具有不同的功能。
自省或反射:给出自身信息的功能,如提供结构,参数,对应函数等信息。
面向对象编程
绑定(binding)
类方法是类内部定义的的函数,不是实例属性,是类属性;
存在实例后,方法才能绑定到类实例上,调用时通过类实例调用;
类中,任何方法定义中第一个参数都是变量self。
调用绑定方法
绑定方法的不同在于与实例绑定,所以调用绑定方法通过实例,不需要给出self参数。
而非绑定方法直接通过类调用(类名加点),且没有实例必须传递self 参数。主要场景
派生一个子类要覆盖父类的方法,如构造方法
classEmplAddrBookEntry(AddrBookEntry):
def __init__(self, nm, ph, em):
AddrBookEntry.__init__(self, nm, ph)
self.empid = id
self.email = em
其中,EmplAddrBookEntry是AddrBookEntry 的子类,其重载了构造器__init__(),其中调用父类的构造器时没有父实例,明确的给出self参数。
Super()函数调用
Python类定义中,方法的第一参数是self,用于传递对象本身,调用时不显示传递。
而在子类中调用父类时,最简单的方法是把对象调用转换成类调用,此时,self参数必须显示传递。也就是说,子类定义时,使用super()调用父类时必须显示传递self参数,如
class FooParent:
defbar(self, message):
print(message)
class FooChild(FooParent):
def bar(self, message):
super(FooChild, self).bar(message)#也可是FooParent.bar(self,message)
调用代码:FooChild().bar("Hello,World.")
其中,子类定义中使用super函数
第一参数是当前子类,
第二参数self
多重继承在super机制里可保证公共父类仅被执行一次,至于执行的顺序按照mro进行的,myclass.__mro__的属性
注意super继承只能用于新式类,用于经典类时就会报错。
新式类:必须有继承的类,如果没什么想继承的,那就继承object
经典类:没有父类,如果此时调用super就会出现错误:『super() argument 1 must be type, notclassobj』
定制类的特殊方法
C.__len__(self) mapping 中的项的数目
C.__hash__(self) 散列(hash)函数值
C.__getitem__(self,key) 得到给定键(key)的值
C.__setitem__(self,key,val) 设置给定键(key)的值
C.__delitem__(self,key) 删除给定键(key)的值
C.__missing__(self,key) 给定键如果不存在字典中,则提供一个默认值
C.__*add__(self,obj) 串连;+操作符
C.__*mul__(self,obj) 重复;*操作符
其中,星号通配符标注的数值二进制操作符则表示这些方法有多个版本,在名字上有些许不同。
"*" 代表''(selp OP obj), 'r'(obj OP self),或'i'(原位(in-place)操作,Py2.0 新增),
例如 __add__, __radd__, or __iadd__.
“*”either nothing (self OP obj), “r” (obj OP self ), or “i” for in-place
operation (new in Python 1.6), i.e., __add__, __radd__, or__iadd__.
实现这些特殊方法将会重载操作符,使它们可以处理你的类类型的实例。比如实例之间的+加号功能通过__add__()实现,而累加通过__iadd__(),右结合加号通过__radd__()实现。
迭代器(Iterator)概述
http://www.cnblogs.com/huxi/archive/2011/07/01/2095931.html
从集合的第一个元素开始访问,直到所有的元素都被访问一遍后结束。
不能回退或者随机访问,只能往前进行迭代
不是线程安全的,在多线程环境中对可变集合使用迭代器是一个危险的操作,使用时小心。
优点:
是不要求事先准备好整个迭代过程中所有的元素。仅仅在迭代至某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等。这个特点被称为延迟计算或惰性求值(Lazyevaluation)。
统一的访问集合的接口。只要是实现了__iter__()方法的对象,就可以使用迭代器进行访问。
Python专门将关键字for用作了迭代器的语法糖。在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素
自己设计迭代器:
迭代器有两个基本方法:
1)next方法:返回容器的下一个元素
2)__iter__方法:返回迭代器自身
在类的__iter__方法中返回一个对象,这个对象拥有一个next()方法,这个方法能在恰当的时候抛出StopIteration异常即可。但是需要自己实现迭代器的时候不多,即使需要,使用生成器会更轻松
授权
包装,是将一段代码重新功能封装,去除不要的,加新的,保留原有的。
派生是对类的包装。
授权是包装的一个特性,最大化代码复用。
新类中,新功能是类的新部分,老功能是直接授权给新类对象来调用,通过覆盖__getattr__()方法。
比如,类的包装就是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。实现授权的关键点就是覆盖__getattr__()方法,在代码中包含一个对getattr()内建函数的调用。
调用getattr()来获得原始对象的属性(在对象的属性列表中存在的数据属性或者方法)。__getattr__()具体的工作方式是,当引用一个属性时,解释器将试着在局部名称空间中查找,比如自定义的方法或局部实例属性。如果失败(局部字典中没有找到),则搜索类名称空间。如果都失败了,搜索则对原对象开始授权请求,调用__getattr__(),其内部用函数getattr()获得原始对象的对应属性。比如,例子
classWrapMe(object):
def__init__(self, obj):
self.__data =obj
def get(self):
returnself.__data
def__repr__(self):
return‘self.__data‘
def__str__(self):
returnstr(self.__data)
def__getattr__(self, attr):
returngetattr(self.__data, attr)
例子中,可以看到将原始对象包装好后,给出__getattr__,比如
wrappedList = WrapMe([123, 'foo',45.67])
封装了列表,则可调用
>>>wrappedList.append('bar')
>>>wrappedList.append(123)
>>>wrappedList
[123,'foo', 45.67, 'bar', 123]
>>>wrappedList.index(45.67)
2
>>>wrappedList.count(123)
2
>>>wrappedList.pop()
123
这些属性是原始对象的属性,当包装类中没有定义,自动调用__getattr__(),通过getattr()方法授权给对象,实现新调用。注意
只有已存在的属性是在此代码中授权的。不是属性的特殊行为,没有在类的方法列表中,不能被访问。比如,列表的切片操作是内建于类型中的,不是属性,则报异常
>>>wrappedList[3]
Traceback(innermost last): File "<stdin>", line 1, in ?
File"wrapme.py", line 21, in __getattr__
returngetattr(self.data, attr)
AttributeError:__getitem__
如果需要调用,可以用get():
>>>realList = wrappedList.get()
>>>realList[3]
或者
>>>wrappedList.get()[3]
to be continue ....