标签:
Python 中的列表(大小可变的数组)和字典(哈希表)就是内建于语言本身的。在核心语言中提供这些重要的构建单元,可以鼓励人们使用它们, 缩短开发时间与代码量,产生出可读性更好的代码。C不提供, c++功能不够简洁。
面向对象,
可升级:Python 提倡简洁的代码设计、高级的数据结构和模块化的组件,确保灵活性、
一致性并缩短必要的调试时间
扩展性:兼容扩展c和java
易读写,易维护
健壮性:Python 提供了“安全合理”的退出机制, Python由于错误崩溃,解释程序就会转出一个“堆栈跟踪”,那里面有可用到的全部信息,包括你程序崩溃的原因以及是那段代码(文件名、行数、行数调用等等)出错了。这些错误被称为异常。如果在运行时发生这样的错误,Python能够监控这些错误并进行处理。描述错误的类型和位置,还能指出代码所在模块。
快速原型开发工具:Python 标准库是很完备的,如果你在其中找不到所需,那么第三方模块或包就会为你完成工作提供可能。
内存管理是由 Python 解释器负责。C 或者 C++最大的弊病在于内存管理是由开发者负责的,会分散精力
类似于Java, Python是字节编译的,可以生成一种近似机器语言的中间形式,提升性能。
Python官网:http://python.org
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 解释器,直接输入脚本名,脚本首行书写的启动指令会自动执行。
Eclipse,pycharm,idle等等,自己搜下.
表示最后一个表达式的值。 所以上面的代码执行之后,下划线变量会包含字符串:
Python 用下划线作为变量前缀和后缀指定特殊变量
_xxx 保护变量不能用’from module import *’导入
__xxx__ 系统定义名字的专用方法
__xxx 类中的私有变量名
程序员避免用下划线作为变量名的开始。
“单下划线” 开头的成员变量叫做保护变量,是只有类对象和子类对象自己能访问到这些变量。这种变量不能直接访问,需通过类提供的接口进行访问,不能用“from xxx import *”而导入。
只以“双下划线”开头的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。
以双下划线开头和结尾的如__foo__,是特殊方法标识,如 __init__()代表类的构造函数。
可实现字符串替换功能,类似C语言:
>>> print "%s is number %d!" % ("Python",1)
Python is number 1!
符号 >> 用来重定向输出,将输出重定向到标准错误输出:
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()
内建函数help()得到一个生疏函数的帮助,用函数名得到相应的帮助信息
>>>help(raw_input)
Help onbuilt-in function raw_input in module __builtin__:
raw_input(...)
raw_input([prompt])-> string
注意,文档字符串的特别注释,是运行时访问,用来自动生成文档,如def foo():
"This isa doc string."
return True
函数名下一行,如果内容多,用三个单引号“’”,就可以跨行了
+ - * / // % **
两种除法运算符,单斜杠用作传统除法,双斜杠用作浮点除法(对结果进行四舍五入)
双星号(**)为乘方运算符,如3 ** 2结果为9
< <= > >= == != <>
不许类型关键字,直接复制
>>>miles = 1000.0
>>>name = ‘Bob‘
>>>counter = counter + 1
支持增量赋值
n = n * 10
n *= 10
不支持自增 1 和自减 1 运算符,--n 解释为-(-n) 从而得到 n , 同样 ++n 的结果也是 n.
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
可以看成是只读的列表。通过切片运算( [ ] 和 [ : ] )可以得到子集,这一点与字符串的使用方法一样。但切片得到的结果也是元组(不能被修改)
>>> 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
接受可迭代对象(例如序列或迭代器)作为其参数,每次迭代其中一个元素。如
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
在一行中使用一个 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
注意,file()内建函数,功能等同于 open(),这个名字可以更确切的表明它是一个工厂函数
可以是简单的数据值,也可以是可执行对象,如函数和方法。
使用“.”访问对象属性,如object.attribute。
代码
filename = raw_input(‘Enter file name: ‘)
fobj = open(filename,‘r‘)
for eachLine in fobj:
print eachLine,
fobj.close()
其中,使用逗号来抑制自动生成的换行符号。文件中的每行文本已经自带了换行字符, 如果我们不抑制 print 语句产生的换行符号, 文本在显示时就会有额外的空行产生。
但对于很大的文件来说, 上面的代码会占用太多的内存, 这时你最好一次读一行。
遇到错误抛出的信息,迅速定位问题并进行调试
代码添加错误检测及异常处理,封装在 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
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
PEP就是一个 Python 增强提案(Python Enhancement Proposal), 这也是在新版Python 中增加新特性的方式。不但提供了新特性的完整描述, 还有添加这些新特性的理由,如果需要的话, 还会提供新的语法、 技术实现细节、向后兼容信息等等。
20、实用的内建函数
dir([obj]) 显示对象的属性,如果没有提供参数, 则显示全局变量的名字
type(obj) 返回对象的类型(返回值本身是一个 type 对象!)
int()
str()
help()
代码跨行写用反斜线 ( \ ),继续上一行
而分号 ( ; )将两个语句连接在一行中
使用四个空格宽度,避免使用制表符
赋值并不是直接将一个值赋给一个变量,尽管其它语言编程如此。但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 这样的前置/后置自增/自减运算
但支持增量赋值,运算符如下
+= -= *= /= %= **=
<<= >>= &= ^= |=
多个变量同时赋值,如x, y, z = 1, 2, ‘a string‘
交换两个变量值想x和y
x, y = 1, 2
x, y = y, x
关键字
专用下划线标识符
_xxx 不用‘from module import *‘导入
__xxx__系统定义名字
__xxx 类中的私有变量名
避免用下划线作为变量名的开始,下划线对解释器有特殊的意义。
变量名_xxx被看作是“私有的”,在模块或类外不可以使用。当变量是私有的时候,用_xxx 来表示变量是很好的习惯。因为变量名__xxx__对Python 来说有特殊含义。
通过obj.__doc__动态获得文档字串。在模块,类声明,或函数声明中第一个没有赋值的字符串可以用属性 obj.__doc__来进行访问,其中 obj是一个模块,类,或函数的名字。
模块结构和布局,推荐的标准风格,如下
使用main()函数,检查__name__ 变量的值
如果模块是被导入, __name__ 的值为模块名字
如果模块是被直接执行, __name__ 的值为 ‘__main__‘
变量无须事先声明
变量无须指定类型
程序员不用关心内存管理
变量名会被“回收”
del 语句能够直接释放资源
(1)动态类型
Python 语言中,对象的类型和内存占用都是运行时确定的。尽管代码被编译成字节码,Python 仍然是一种解释型语言。在创建事,也就是赋值时,解释器会根据语法和右侧的操作数来决定新对象的类型。
(2)内存分配
Python 解释器承担了内存管理的复杂任务,底层的事情放心交给 Python 解释器
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 模块。明显的缺点需要花较长时间从日志文件中载入分析结果, 不支持子函数状态细节及某些结果不准确。
身份:每个对象唯一的身份标识,使用内建函数id()来得到,可以认为是对象的内存地址。不用关心。
类型:内建函数type()查看对象类型,返回值为对象非字符串。类型决定值、操作、规则,如
type(type(42))
<type ‘type‘>
值:对象数据项
特殊类型NoneType:只有一个值None,没有任何运算,没有任何内建方法。布尔值总是False。
(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 :返回一个对象
(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),不过这个范围是会改变的,所以请不要在你的应用程序使用这个特性。
另外,预定义缓存字符串表之外的字符串,不再有任何引用指向它,那这个字符串将不会被缓存。对象回收器一样可以回收不再被使用的字符串
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语句输出。
比type()好一点,功能一样。因为提升性能方法:
(1)减少函数调用次数(尽量使用变量做比较项目)
(2)减少查询次数,from-import,你可以减少一次查询:
from typesimport IntType
if type(num)is IntType...
Python 2.2 统一了类型和类,所有内建类型也都是类。其内建转换函数如 int(), type(), list() 等等,都是类。看着像函数,实际是类。调用时也是生成实例。
“基本” ,是指这些类型都是 Python 提供的标准或核心类型。
“内建” ,是由于这些类型是 Python 默认就提供的
“数据” ,因为他们用于一般数据存储
“对象” ,因为对象是数据和功能的默认抽象
“原始” ,因为这些类型提供的是最底层的粒度数据存储
“类型” ,因为他们就是数据类型
标量/原子类型 数值(所有的数值类型) ,字符串(全部是文字)
容器类型 列表、元组、字典
可变类型 列表, 字典
不可变类型 数字、字符串、元组
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模块
Python 标准整数类型等价于C中(有符号)长整型。八进制整数以数字“0”开始,十六进制整数则以“0x” 或“0X” 开始
整数值后面加个 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
。 每个浮点数占8个字节 (64比特) , 完全遵守IEEE754号规范 (52M/11E/1S) , 其中 52 个比特用于表示底,11 个比特用于表示指数(可表示的范围大约是正负 10 的 308.25次方) , 剩下的一个比特表示符号。但实际精度依赖于机器架构和创建 Python 解释器的编译器。
“+”对不用类型不同操作,不仅是加法
整数转换为浮点数, 非复数转换为复数。Python 提供了coerce()内建函数来帮助你实现这种转换。
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
取反(~),按位 与(&),或(|)及 异或(^)及左移(<<)和右移(>>)只支持整数。
五个数值运算内建函数:
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 性能更好
(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
天生缺憾的表达,如
>>> 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/
randint()两个整数参数,返回二者之间的随机整数
randrange() 它接受和 range()函数一样的参数, 随机返回
range([start,]stop[,step])结果的一项
uniform() 几乎和 randint()一样,不过它返回的是二者之间的一个浮点数(不包括范围上限)。
random() 类似 uniform() 只不过下限恒等于 0.0,上限恒等于1.0
choice() 随机返回给定序列(关于序列,见第六章)的一个元素
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] # 隔一个取一个的操作
序列本身内含迭代的概念,是简单的迭代器。
(1)各类型之间的转换:转换实际上是工厂函数,将参数的内容(浅)拷贝到新生成对象
list(iter) 把可迭代对象转换为列表
str(obj) 把 obj 对象转换成字符串(对象的字符串表示法)
unicode(obj) 把对象转换成 Unicode 字符串(使用默认编码)
basestring() 抽象工厂函数,其作用仅仅是为 str 和 unicode 函数提供父类,所以不能被实例化,也不能被调用
tuple(iter) 把一个可迭代对象转换成一个元组对象
其中,建立python后不能更改其身份或类型。建立一个浅拷贝,只拷贝了对象的索引,而不是重新建立了一个对象。
注意,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"
性能的的角度,把重复操作作为参数放到循环里面进行是非常低效的,如
while i < len(myString):
print ‘character %d is:‘, myString[i]
其中,len(myString)每次都被计算,浪费资源,改成
length = len(myString)
while i < length:
%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
>>>s, t = ‘foa‘, ‘obr‘
>>>zip(s, t)
[(‘f‘, ‘o‘),(‘o‘, ‘b‘), (‘a‘, ‘r‘)]
str()和 unicode()函数都是工厂函数,就是说产生所对应的类型的对象,它们和basestring都可以作为参数传给isinstance()函数来判断一个对象的类型
>>>isinstance(u‘\0xAB‘, str)
False
>>>not isinstance(‘foo‘, unicode)
True
>>>isinstance(u‘‘, basestring)
True
>>>not isinstance(‘foo‘, basestring)
False
字符串前加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 之外到底使用的是那种平面,
Python 标准库里面的绝大部分模块都是兼容 Unicode 的。但pickle 模块只支持 ASCII 字符串。如果你把一个 Unicode 字符串交给 pickle 模块来 unpickle,它会报异常.你必须先把你的字符串转换成 ASCII 字符串才可以.所以最好是避免基于文本的 pickle 操作.幸运地是现在二进制格式已经作为 pickle 的默认格式了,pickle 的二进制格式支持不错.这点在你向数据库里面存东西是尤为突出,把它们作为BLOB字段存储而不是作为TEXT或者VARCHAR字段存储要好很多.万一有人把你的字段改成了 Unicode 类型,这可以避免 pickle 的崩溃.
另外,使用第三方模块时要注意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 用的内部格式
模块 描述
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数据库
不需要像C一样添加结束符,python自动管理,字符串中只包含你所定义的东西,没有别的。
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,则列表以反序排列.
python方法不一定有返回值,如sort(),extend()和 reverse()这些操作在列表中原地执行操作,原列表内容被改变,没有返回值。与之相反,字符串不能被改变,所以这些函数产生新对象,一定会有返回值。
元组也没有它自己专用的运算符和内建函数,因为元组是不可变的,没有实现排序,替换,添加等方法
但元组也可以间接的变化,如两个元组用加号+连接;或者元组元素为列表,就可以增减元素。
注意,有符号封装的多对象集合其实是返回的一个单一的容器对象,如
def foo1():
:
return obj1,obj2, obj3 #等同于return (obj1, obj2, obj3)
(‘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 高性能容器数据类型
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()等等。
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}
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
在 while 和 for 循环中使用else语句,else子句在循环完成后,最后执行, 如果有break语句则会跳过else块。
迭代器一组数据结构,利用引从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()返回前文件指针在文件中的位置。从文件起始算起,单位为字节。
目前,使用文件迭代是最高效的方法,直接
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。
(将多个函数的相同功能代码提取成一个装饰函数,用@+函数名放在函数前直接调用,实际是将被装饰函数作为参数传入装饰函数中,返回新的参数对象,原有被装饰函数对象作废)
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是被装饰函数名,而内部是包装的执行函数。也就是说有参数传入加一层。
在函数内部定义一个内部函数(嵌套函数),其引用了外部作用域的变量,并且不是全局变量,那么这个内部函数叫闭包。装饰器就是闭包。
函数调用自身叫递归,典型例子,阶乘factorial(N)= N* factorial(N-1),求N项值需要知道N-1项值。
生成器是带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。
(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语句放入函数内部。不要放在开头。
封装:数据属性对外隐藏,自身设计访问方法供外部使用
合成:将多个类合成一个类
泛化:提取共性做成父类
特化:设计新功能的子类
多态:调用不同对象的相同名称的函数,却具有不同的功能。
自省或反射:给出自身信息的功能,如提供结构,参数,对应函数等信息。
类方法是类内部定义的的函数,不是实例属性,是类属性;
存在实例后,方法才能绑定到类实例上,调用时通过类实例调用;
类中,任何方法定义中第一个参数都是变量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参数。
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__()实现。
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 ....
pthon核心编程-读书笔记:知识点摘录与总结(方便理解和快速记忆)
标签:
原文地址:http://blog.csdn.net/longshenlmj/article/details/51626773