Python 点滴 I

为什么使用Python

1. 软件质量:   Python更注重软件质量,一致性,可维护性

2. 开发效率:   相比C/C++/Java这些编译/静态语言,无需编译及链接步骤,Python所须要的代码仅仅有其1/5到1/3,

3. 可移植性:   程序不需做不论什么修改。可在不论什么平台执行

4. 标准库支持: 标准库及第三方库许多

5. 组件集成:   能够集成机制非常方便的与其它部分进行通信,C/C++/Java/,及.COM..NET进行通信

6. 好玩:       易用性及强大的内置工具使编程成为一种乐趣

质量和效率。是Python最吸引人的地方。

Python的缺点

或许是唯一的缺点: 相比較C/C++/Java这些编译语言比,Python的运行速度还不够快.

Python的实现方式: 源程序==>编译为字节码==>再通过PVM解释出来. 由于Python没有将代码编译为底层芯片能识别的二进制码,一些Python程序会比上述语言慢一些。在这里由于Python中的非常多内置函数就是C开发出来的来。因此它有与C相同的速度。所以尽可能的使用内置函数,避免使用纯粹的Python代码.Python开发速度带来的效益会远超运行速度代码的损失.Python的每一个版本号。都对速度方面做了优化,况且在当今硬件资源日益强大的今天。这些甚至都不是缺点。

Python GUI

Tkinter,Qt,wxPython,MFC,Swing,GTK

Python WEB开发框架

Django,Web.py,Zope, WebWare, TurboGears

Python应用的领域

系统编程

GUI

Internet脚本

组件集成

数据库编程

高速原型

科学计算及数据分析

游戏、图像、XML、人工智能、机器人等

Python差点儿能用于全部领域

Python功能强大

动态类型

自己主动内存管理

大型程序支持

内置对象类型

库工具

第三方工具

Python全景

#模块,语句,表达式,对象)

1. 程序由模块组成

2. 模块包括语句

3. 语句包括表达式

4. 表达式建立并处理对象

动态类型

Python即是动态类型又是强类型,在C/C++/Java强类型语言中。要先声明。后使用

动态类型:自己主动跟踪用户定义的类型而不须要预先定义 

s=1的话, s*2就等于2

s='hello'的话, s*2就等于'hellohello'

random模块

1. 可做随机数生成器

>>> import random
>>> random.random()
0.26637487298372353

2. 可做随机选择

>>> random.choice([1,2,3,4,5,6]);random.choice(range(12))
2
7

【使用元祖的优点

.元祖比列表速度快,假设一组常量值不过遍历,那么无疑应该选择元祖

.对不须要改动的数据进行写包括,用元祖而不是列表

.字典中的键,能够是:数字,字符串或元祖等不变对象。但不是能是列表。因列表可变

.元祖用在字符串的格式化很实用

>>> (Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday)= range(7)
>>> Monday
0

序列

#字符串,列表及元祖

>>> S = 'A B C'
>>> len(S)
5

>>>s = 'Spam'

>>>s[::-1]    #反向切片

'mapS'

>>>'B'+s[1:]  #字符拼接

'Bpam'

>>> y = s[:]  #用于字符串的深度拷贝 

'Spam'

#Python中的多态: 操作的意义取决于操作的对象,给Python带来更大的简洁性和灵活性.

>>>s + 'xyz'    

'Spamxyz' 

>>> s = 1;  s + 2;

3

#字符串不可变性,在Python核心类型中,

不可变: 数字,字符串,元祖

可变  : 列表,字典

>>> s = 'Spam'
>>> s[0] = 'X'  #字符串不可更改
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

>>> s[0]+'X'    #可是我们创造新的对象,不改变原来的字符串
'SX'
>>> s
'Spam'

>>> s.replace('pam','B') #运用replace方法,事实上是创建了新的字符串对象
'SB'
>>> s                    #不会改变原字符串的值
'Spam'

寻求帮助

首选:dir和help

其次:Python标准库參考文件(本地) 和 https://www.python.org/doc/(官方站点)

>>> dir(s)  #__开头:变量名,用来表示Python的实现细节的命名规则,其它则为方法
['__add__', '__class__','__doc__','index','ljust', 'lower', 'lstrip', 'partition', 'replace',
'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit','zfill']

>>> help(s.zfill) #dir给出了方法列表,详细怎样使用求助于help
Help on built-in function zfill:

zfill(...)
    S.zfill(width) -> string


    Pad a numeric string S with zeros on the left, to fill a field
    of the specified width.  The string S is never truncated.

列表

可变,比数组强大,无规定类型的约束

>>> l = [123,1.23]
>>> l.append('Hello')

>>> l
[123, 1.23, 'Hello']
>>> l.pop(1)
1.23
>>> l
[123, 'Hello']

嵌套

核心数据支持随意的嵌套。列表包括字典,并在字典中包括另外一个列表,直接应用时实现矩阵,或者多维数组。

>>> M = [[1,2,3],
         [4,5,6],
         [7,8,9]]
>>> M
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

>>> M[1]      #取第二行
[4, 5, 6]
>>> M[1][2]   #最后一个元素
6

【append和extend差别

>>> L1 = ['a','b']
>>> L1.append(['c','d'])
>>> L1
['a', 'b', ['c', 'd']]
>>> L1 = ['a','b']
>>> L1.extend(['c','d'])
>>> L1
['a', 'b', 'c', 'd']

NOTE:

1. extend接收一个參数。这个參数仅仅能是列表。并将列表中的元素加入原列表中

2. append接收一个參数,能够是不论什么对象,讲其作为总体加入到原列表中.

列表解析

更高级的列表操作(list comprehension expression)列表解析表达式,提供了能够处理矩阵这种强大工具,实际上非常实用。且有速度上的优势(一般快两倍)。返回是列表.

>>> cols = [row[1] for row in M]             #取每行元素的第二列
>>> cols
[2, 5, 8]

>>> [row[1]+1 for row in M]                  #在原先的基础上+1
[3, 6, 9]
>>> [row[1] for row in M if row[1]%2 == 0]   #用if语句仅仅取偶数那部分
[2, 8]

>>> diag = [M[i][i] for i in [0,1,2]]        #取M[0][0],M[1][1],M[2][2]
>>> diag
[1, 5, 9]

>>> double = [s *2 for s in 'SB']
>>> double
['SS', 'BB']

字典

可变,非序列,Python中唯一的映射型。映射是一种其它对象的集合,它们是通过键而不是相对位置来存储.键无序,仅仅是简单将键映射到值. {键:值}。由于字典是无序的,所以,取出来的未必是我们想要的。

>>> d = {'a':1,'b':2,'c':3}
>>> d
{'a': 1, 'c': 3, 'b': 2}

假设真要排序的话,用sort.

>>> ks = d.keys()
>>> ks
['a', 'c', 'b']
>>> for key in ks:
print key, '==>', d[key]


a ==> 1
c ==> 3
b ==> 2
>>> ks.sort()
>>> ks
['a', 'b', 'c']
>>> for key in ks:
print key,'=>', d[key]

a => 1
b => 2
c => 3

或者

>>> d
{'a': 1, 'c': 3, 'b': 2}
>>> for key in sorted(d):
print key,'=>',d[key]

a => 1
b => 2
c => 3

小技巧:键值推断if

>>> D
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
>>> D.has_key('e')
False

>>> if not D.has_key('e'):
print 'e key missing...'
e key missing...

这里能够使用(get方法,成员表达式,try语句捕捉异常)来避免键值不存在.

file

Python核心类型, 字符串,列表,字典,元祖。文件

注意f.read()和f.readlines()差别,前者读取是字符串,后者返回为列表.

>>> f = file('data.txt','w')
>>> f.write('Hello ')
>>> f.write('World ')
>>> f.close()

>>> f = file('data.txt')
>>> f1 = f.read()
>>> f1
'Hello World '
>>> f1.split()
['Hello', 'World']

>>> f = open('data.txt')
>>> f.readlines()
['Hello ', 'World ']

open函数能实现绝大多数文件如理,Python提供额外的文件类工具来处理更高级的任务:pipes, fifos, sockets, keyed-access files, 对象持久,基于描写叙述符的文件,关系数据库和面向对象数据库接口。

破坏代码的灵活性

#至少能够用以下的三种方法来校验代码的灵活性

>>> if type(L) == type([]):
print 'Yes'
Yes

>>> if type(L) == list:
print 'Yes'
Yes

>>> if isinstance(L,list):
print 'Yes'
Yes

#在代码中检验了特定的类型。实际上破坏了它的灵活性,即限制它仅仅能使用一种类型工作。没有这种測试。代码或许能够使用整个范围的类型工作。这个Python多态的思想.是其关键的思想.虽然Python是面向对象语言。但类是Python的一个可选特性,Python即能够使面向过程语言。也能够使面向对象的语言。非常灵活.

str和repr

从技术上来说,默认的交互模式和打印模式的差别相当于repr和str函数的差别

>>> num
0.3333333333333333
>>> repr(num)
'0.3333333333333333'
>>> str(num)
'0.333333333333'

这两个函数都会把随意对象变换成它们的字符串表达。

repr:默认的交互式回显,产生的结果看起来就像它们是代码

str:  打印语句,变换得到一种对用户更加友好的格式.

/ 除法运算

>>> 5/2
2

>>> from __future__ import division  #导入未来可能採用的模式的结果
>>> 5/2
2.5

八进制和十六进制

八进制: 0开头,并紧跟八进制数字0-7的字符串

十六进制:以0x,0X开头,后面0-9数字或(a-Af-F)构成的字符串

>>> 01,010,0100
(1, 8, 64)
>>> 0x01,0X10,0xFF
(1, 16, 255)

能够用对应的函数在进制之间转化:

>>> oct(64),hex(255)    #将十进制分别转为八进制。十六进制
('0100', '0xff')

>>> int('0100'),int('0100',8),int('0100',16) #int函数分别加要转换的进制,默认是10进制
(100, 64, 256)

也能够用eval函数

>>> eval('100'),eval('0100'),eval('0x100')

(100, 64, 256)

假设想通过字符串表达式来表示,则能够用例如以下方式:

>>> '%d %o %x %X' % (100,64,255,255)
'100 100 ff FF'

小数对象

>>> 0.1 + 0.1 + 0.1 - 0.3         #直接回显
5.551115123125783e-17

>>> print 0.1 + 0.1 + 0.1 - 0.3   #用打印,显示友好,但改善不大
5.55111512313e-17

>>> from decimal import Decimal   #必须导入decimal模块
>>> Decimal('0.1')+Decimal('0.1')+Decimal('0.1')-Decimal('0.3')
Decimal('0.0')

>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1428571428571428571428571429')

>>> decimal.getcontext().prec = 4
>>> Decimal(1)/Decimal(7)
Decimal('0.1429')

Pyton的动态类型

在Python中。类型是执行过程中自己主动决定的,而不是代码声明.

对象的垃圾收集

>>> a = 1            #先给变量a赋值整数1
>>> a = 'New Year!'  #再给字符串的引用赋给a

>>> a = [1,2,3,4]

则前一个对象占用的空间就会被回收(如果。它没有被其他对象或变量名引用的话).在Python中类型属于对象,变量名仅仅是对象的引用.对象的引用值在此过程中逐个被丢弃。每一次a被赋值给了一个新对象,Python都回收了对象的空间. 当它赋值为[1,2,3,4]时。对象1,和'New Year'立即会被回收,如果它没有其他对象引用的话: 对象的空间自己主动放入自由内存空间池。等待后面的对象使用. 

在内部Python是通过保持用每一个对象中的计数器记录引用指到这个对象上的次数来完毕这一功能。一旦这个计数器被设置为0。这个对象的内存空间就会自己主动回收。

像前面一样,a每次被赋值给一个新对象,而前一个对象的引用计数器变为0,导致它的空间被回收。

垃圾收集最直接,可感受的优点就是:能够再脚本中随意使用对象而不须要考虑释放内存空间. 在程序执行时,Python将会清理那些不再使用的空间。 和C/C++这些底层语言相比,省去了大量的基础代码。 Python会使用引用值计算的垃圾收集策略,自己主动回收无用对象的内存空间。

每一个对象都会记录引用其的变量名。数据结构等次数,一旦计数值为0,Python就会释放该对象的空间。这样的方式意味着Python不用停下来扫描全部内存,从而寻求释放的无用空间. 注:一个额外的垃圾组件也会收集循环对象

共享引用和原处改动

Python中可变的对象:列表。字典和class中定义的对象

列表支持原处改动。所以在列表中进行改动会改变其值.

>>> L1 = [2,3,4]
>>> L2 = L1
>>> L1[0]=1
>>> L1;L2
[1, 3, 4]
[1, 3, 4]

要想L2的值不做修改的话,必须对L1做一份拷贝.

>>> L1 = [1,2,3]
>>> L2 = L1[:]  #一个有同样的值,但在不同内存片区的对象
>>> L1[0]=21
>>> L1;L2
[21, 2, 3]
[1, 2, 3] 

>>> import copy
>>> Y = 1
>>> X = copy.copy(Y)
>>> X = copy.deepcopy(Y)

【检查变量相等

Python中有两种方法来检查两个变量是否相等.例如以下: 

>>> L = [1,2,3]
>>> M = L
>>> L == M  #==操作符,測试两个被引用的对象的值是否相等,在Python用作相等检查
True
>>> L is M  #is操作符号,检查引用对象的同一性.假设两个变量名指向同一个对象,则为Ture
True

再看以下一种情况:

>>> M = [1,2,3]
>>> L = [1,2,3]  #M,L为两个不同的object
>>> M == L       #M,L的值是相等的
True
>>> M is L       #M,L为不同的Object,即不同的内存块
False
>>> id(M);id(L)
41080456L
41083848L

可是假设是数字类型的话,会有小许区别.

>>> X = 42
>>> Y = 42
>>> X == Y    #值显然同样
True
>>> X is Y #由于数字和字符串被缓存并复用了,所以两者是同一个对象.
True

假设深究的话,能够查询一个对象被引用的次数,用sys模块中的getrefcount函数

>>> import sys
>>> sys.getrefcount(42) #查看42这个数字被引用的次数,有13次反复引用
13

>>> str(u'spam');unicode('spam') #普通字符串和unicode字符串相互转化

'spam'
u'spam'

切片操作的实际应用

1. [:]能够用这个来做深度拷贝

2. import sys
print sys.argv[1:]    #查看參数个数。文件名称不包含在内

输出结果:

D:python>python echo.py  -help -start -stop
['-help', '-start', '-stop']

3. 文本操作,去掉最末 (换行符)line[:-1]

当然也能够用rstrip()去掉后面的换行符

字符串转换工具

>>> int("42");str(42)
42
'42'
>>> repr(42),`42`
('42', '42')

其它转换

>>> float("1.5")
1.5

>>> text = "1.234E-10"
>>> float(text)
1.234e-10

对应的可用内置函数eval来进行操作

字符串代码转换

>>> (115, 's')
(115, 's')

>>> S = '5'
>>> S = chr(ord(S)+1)
>>> S
'6'

>>> ord('5') - ord('0')
5

#转换能够与循环语句配合使用,能够将一个表示二进制的字符串转换为等值的整数--每次都将当前的值*2,并加上下一位数字的整数值

>>> B = '1101'
>>> I = 0
>>> while B:
...   I = I*2 + (ord(B[0])-ord('0'))
...   B = B[1:]
...
>>> I
13

字符串格式化

>>> x 
1.2345678899999999
>>> "%-6.2f | %05.2f | %+06.1f" % (x,x,x)  #(-)左对齐,(+)正负号,(0)补齐,整数,小数点后位数
'1.23   | 01.23 | +001.2'

>>> "%s" % x,str(x)     #两者效果一样
('1.23456789', '1.23456789')

#基于字典的字符串格式化,同意右边字典中键来提取相应的值。在生成XML或HTML程序中往往会应用这一技术。你能够建一个数值字典,并利用基于键的引用的格式一次性替换他们.

>>> "%(name)s age is: %(age)s " % {'name':'Bob','age':40}
'Bob age is: 40 '

再比方:

>>> reply = '''
... Greeting...
... Hello %(name)s!
... Your age squared is %(age)s
... '''
>>> values = {'name':'Bog','age':40}
>>> print reply % values

Greeting...
Hello Bog!
Your age squared is 40

这种小技巧也常与内置函数vars联起来一同使用,这个函数返回的字典包括了全部在本函数调用时存在的变量

>>> food = 'spam'
>>> age  = 40
>>> vars()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'food': 'spam', 'ages': 40, '__doc__': None}
>>> "%(age)d %(food)s" % vars()
'40 spam'

>>> "aa$bbb$cc$".replace('$','SB')  #replace,能够替换不定长的字符串
'aaSBbbbSBccSB'

#有点繁琐的替换

>>> S = 'xxxxSPAMxxxxSPAMxxxx'
>>> W = S.find('SPAM')
>>> W
4
>>> S = S[:W]+'EGGS'+S[W+4:]
>>> S
'xxxxEGGSxxxxSPAMxxxx'

#因为字符串是不可更改。replace每次生成一个新的对象

>>> S = 'xxxxSPAMxxxxSPAMxxxx'
>>> S.replace('SPAM','EGGS')
'xxxxEGGSxxxxEGGSxxxx'
>>> S = 'xxxxSPAMxxxxSPAMxxxx'
>>> S.replace('SPAM','EGGS',1) #替换一个
'xxxxEGGSxxxxSPAMxxxx'

#以下是第二种替换的方式

>>> S = 'spammy'
>>> L = list(S)
>>> L
['s', 'p', 'a', 'm','m','y']
>>> L[2] = 'x'

>>> L[3] = 'x'
>>> S = ''.join(L)
>>> S
'spaxxy'
split

split,默认是TAB,空格来切割,也能够,或其它切割符,当然也能够是长字符串

>>> S = "This'sSPAMaSPAMdog!"
>>> S.split('SPAM')
["This's", 'a', 'dog!']

列表

Python中最灵活的有序集合对象类型,能够包括不论什么类型。可原处改动. 在列表中,删除某个片段和赋空值是等价的

>>> L = [1,2,3,4]
>>> del L[1:3]
>>> L
[1, 4]

>>> L = [1,2,3,4]
>>> L[1:3] = []
>>> L
[1, 4]

【get

字典中,防止取不到值,能够用get,不至于报错:

>>> D2
{'eggs': 3, 'ham': 1, 'spam': 2}
>>> D2.get('spam')
2

>>> D2.get('hamm') #不存在的话,为None
>>> D2.get('hamm','Key Error: The key not exist!') #能够自己定义输出
'Key Error: The key not exist!'

字典中的update方法

类似于列表中的合并

>>> D2
{'eggs': 3, 'ham': 1, 'spam': 2}
>>> D3 = {'toast':4,'muffn':5}
>>> D2.update(D3)
>>> D2
{'toast': 4, 'muffn': 5, 'eggs': 3, 'ham': 1, 'spam': 2}

如有反复键的话,则会覆盖

>>> D2 = {'eggs': 3, 'ham': 1, 'spam': 2}
>>> D3 = {'eggs':4}
>>> D2.update(D3)
>>> D2
{'eggs': 4, 'ham': 1, 'spam': 2}

字典中的一个应用

>>> table = {'Python':'Guido van Rossum',
...          'Perl'  :'Larry Wall',
...          'Tcl'   :'John Ousterhout'}
>>> language = 'Python'
>>> creator  = table[language]
>>> creator
'Guido van Rossum'
>>> for lang in table.keys():
...   print lang,' ',table[lang]
...
Python  Guido van Rossum
Tcl     John Ousterhout
Perl    Larry Wall


字典中经常使用的遍历

>>> D1
{'eggs': 3, 'ham': 1, 'spam': 2}
>>> for key,value in D1.items():    #按照键,值来遍历 D1.items()
...   print key,' ',D1[key]
...
eggs    3
ham     1
spam    2
>>> for key in D1.keys():           #遍历键
...   print key,
...
eggs ham spam
>>> for value in D1.values():       #遍历值
...   print value,
...
3 1 2

使用字典模仿灵活的列表

>>> L = []
>>> L[99] = 'spam'   #在列表中这样使用是错误的。不能越界。列表有序,有界
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range

但在字典中却能够,由于字典是无序。无界

>>> D = {}
>>> D[99] = 'spam'
>>> D
{99: 'spam'}

字典用于稀疏数据结构

即稀疏矩阵

>>> M = {}
>>> M[(2,3,4)] = 88   #用于存储坐标为(2,3,4)的值
>>> M[(5,6,7)] = 99   #用于存储坐标为(5,6,7)的值
>>> M
{(2, 3, 4): 88, (5, 6, 7): 99}
>>> X = 2;Y = 3;Z = 4;
>>> M[(X,Y,Z)]        #依据坐标来查找其值
88
>>> M[(2,3,5)]        #该坐标不存在,所以报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: (2, 3, 5)


避免missing-key错误: 从编程的角度来看,get方法是当中最简单的。

能够用以下三种方法来避免missing-key的错误:

1. 用if来推断

>>> if M.has_key((2,3,6)):
...   print M[(2,3,6)]
... else:
...   print 0
...
0

2. 用try来扑捉异常

>>> try:
...   print M[(2,3,6)]
... except KeyError:
...   print 0
...
0

3. 用get方法

>>> M.get((2,3,6),0)  #不存在的话。显示后面的信息
0
>>> M.get((2,3,4),0)  #如存在的话,显示找到的坐标值
88

字典扮演的角色

1.字典能够代替搜索数据结果。由于用键进行索引是一种搜索操作,字典事实上是一种哈希索引

2.还能够表示各种结构化信息.

#比方以下,随时通过新键赋值来填写字典的样例

>>> rec['age']  = 45
>>> rec['name'] = 'mel'
>>> rec['age']  = 45
>>> rec['job']  = 'trainer/writer'
>>> print rec['name']
mel

#特别是嵌套的时候,Python能够非常轻松的表达结构化信息

>>> mel = {'name':'Mark',
...        'jobs':['trainer','writer'],
...        'webs':'www.xxx.com',
...        'home':{'state':'CD','zip':80513}}

当读取嵌套函数时,仅仅须要把索引操作串起来就可以:

>>> mel['name'];mel['jobs']
'Mark'
['trainer', 'writer']

>>> mel['jobs'][1]
'writer'
>>> mel['home']['zip']
80513

创建字典的五种方法

方法一:

#假设事先能拼出整个字典。则此方法比較方便

>>> D1 = {'name':'Bob','age':40}

方法二:

#假设须要动态地建立字典的一个字段,则此方法比較方便

>>> D2 = {}
>>> D2['name'] = 'Bob'
>>> D2['age']  =  40
>>> D2
{'age': 40, 'name': 'Bob'}

方法三:

#keyword形式,代码比較少。但键必须为字符串型。经常使用于函数赋值

>>> D3 = dict(name='Bob',age=45)
>>> D3
{'age': 45, 'name': 'Bob'}

方法四:

#假设须要将键和值逐步建成序列。则这样的方式比較实用。常与zip函数一起使用
>>> D4 = dict([('name','Bob'),('age',40)])
>>> D4
{'age': 40, 'name': 'Bob'}

方法五:

#假设键的值都同样的话,用这样的方式比較好,并能够用fromkeys来初始化

>>> D5 = dict.fromkeys(['A','B'],0)
>>> D5
{'A': 0, 'B': 0}

字典接口

Python扩展程序提供了和字典类似的接口,字符串的值都通过键来读取。比如:

>>> import anydbm                       #导入模块,shelve也相似
>>> file = anydbm.open('test.db','n')   #保存的文件test.db, 
>>> file['name'] = 'Bruce Li'           #存储键为name的数据
>>> file['jobs'] = 'writer/fighter/poet'#存储键为jobs的数据
>>> file['ages'] = '40'                 #存储键为ages的数据
>>> data  = file['jobs'].split('/')[1]  #读取键为jobs中数据
>>> print data                          #仅仅能存储String或None型数据
fighter

#下面是cgi模块的接口,也是字典中映射的样例

>>> import cgi
>>> form  = cgi.FieldStorage()          #来自data中的參数
>>> if form.has_key('name'):
...   showReply('Hello,' + form['name'].value)

单个元素的元祖

>>> t1 = (0); type(t1)     #整数
<type 'int'>
>>> t1 = (0,); type(t1)    #单个元素的元祖
<type 'tuple'>

#以下两种方式是一样的,第一种方式经经常使用于字符串格式化输出

>>> t2 = (0,'Hello',3.14)  #也用于函数传递实參
>>> t2 =  0,'Hello',3.14   #最好统一用上()

元祖排序

#由于元祖不提供排序方法,所以要先转为列表

>>> T = ('cc','aa','dd','bb')
>>> L = list(T)           #转为列表
>>> L
['cc', 'aa', 'dd', 'bb']
>>> L.sort()              #再对列表排序
>>> L
['aa', 'bb', 'cc', 'dd']
>>> id(T)                 #查看内存中的ID号
48151032L
>>> T = tuple(L)
>>> T
('aa', 'bb', 'cc', 'dd')
>>> id(T)                 #ID号码已经发生了改变,也就是生成了新的对象
48253032L

元祖元素

NOTE:元祖顶层元素不可更改,但元祖里面的列表的值是能够改动的。例如以下

>>> T = (1,[2,3],4)
>>> T[1] = 'spam'         #顶层元素不可更改
Traceback (most recent call last):
  File "<pyshell#193>", line 1, in <module>
    T[1] = 'spam'
TypeError: 'tuple' object does not support item assignment
>>> T[1][1] = 'three'    #里面子列表元素能够更改
>>> T
(1, [2, 'three'], 4)

在文件里存储并解析Python对象

#创建

>>> X,Y,Z = 43,44,45
>>> S     = 'spam'
>>> D     = {'a':1,'b':2}
>>> L     = [1,2,3]
>>> F     = open('data.txt','w')
>>> F.write(S+' ')
>>> F.write('%s,%s,%s ' % (X,Y,Z))
>>> F.write(str(L)+'$'+str(D)+' ')
>>> F.close()

#读取

>>> bytes = open('data.txt').read()
>>> bytes         #交互模式回显
"spam 43,44,45 [1, 2, 3]${'a': 1, 'b': 2} "
>>> print bytes   #会解释内嵌行终止符给予用户惬意的答案
spam
43,44,45
[1, 2, 3]${'a': 1, 'b': 2}

#解析

>>> F = open('data.txt')
>>> line = F.readline()   #读取一行
>>> line                 
'spam '

>>> line[:-1]             #用切片方式去除后面的换行符
'spam'
>>> line.rstrip()         #用rstip()函数去除后面的换行符
'spam'

#继续解析

>>> line = F.readline()    #读取下一行
>>> line                  
'43,44,45 '
>>> parts = line.split(',')#以逗号来分离
>>> parts
['43', '44', '45 ']
>>> int(parts[1])          #int转为整型,会忽略换行符,空白符
44
>>> numbers = [int(P) for P in parts] #列表解析
>>> numbers
[43, 44, 45]

#最后解析

>>> line = F.readline()
>>> line
"[1, 2, 3]${'a': 1, 'b': 2} "
>>> parts = line.split('$')
>>> parts
['[1, 2, 3]', "{'a': 1, 'b': 2} "]
>>> eval(parts[0])         #将字符串转为随意object目标
[1, 2, 3]
>>> objects = [eval(P) for P in parts] #列表解析
>>> objects
[[1, 2, 3], {'a': 1, 'b': 2}]

用pickle存储Python的原生对象

eval可将字符串转为对象。有时功能太强大会出问题。假设想存储原生对象,又无法信赖文件的数据来源,pickle是个理想的选择。能够存储差点儿Python对象的高级工具,不须要像上面那样转来转去。它是超级通用的数据格式化和解析工具.看以下样例

>>> D
{'a': 1, 'b': 2}
>>> F = open('datafile.txt','w')
>>> import pickle
>>> pickle.dump(D,F)         #pickle any object to file
>>> F.close()
>>>
>>> F = open('datafile.txt') 
>>> E = pickle.load(F)       #load any object from file.
>>> E
{'a': 1, 'b': 2}

文件里打包二进制数据的存储与解析

struct模块可以构造并解析打包的二进制数据,它是还有一个数据转换工具。可以把文件里的字符串解读为二进制数据.

>>> F = open('data.bin','wb')                    #Open binary output file
>>> import struct
>>> bytes = struct.pack('>i4sh',7,'spam',8)      #Make packed binary file
>>> bytes
'x00x00x00x07spamx00x08'
>>> F.write(bytes)                               #Write byte string
>>> F.close()


>>> F = open('data.bin','rb')
>>> data = F.read()                              #Get packed binary data
>>> data
'x00x00x00x07spamx00x08'
>>> values = struct.unpack('>i4sh',data)         #Convert to Python Objects
>>> values
(7, 'spam', 8)

对象的灵活性

1. 列表,字典和元祖能够包括不论什么种类的对象

2. 列表,字典和元祖能够随意嵌套

3. 列表和字典能够动态扩大和缩小

拷贝

1. L[:]可以复制序列

2. 字典copy方法可以复制字典

3. 有些内置函数,可以生产拷贝.比方说list(L)

4. copy标准库模块可以生产完整拷贝

>>> L = [1,2,3]
>>> A = L[:]
>>> D = {'a':1,'b':2}
>>> B = D.copy()

>>> A[1]='Ni'
>>> B['c']='spam'
>>> L,D
([1, 2, 3], {'a': 1, 'b': 2})
>>> A,B
([1, 'Ni', 3], {'a': 1, 'c': 'spam', 'b': 2})

#所以复杂点的样例来说:

>>> X = [1,2,3]
>>> L = ['a',X[:],'b']        #嵌套拷贝X的对象
>>> D = {'x':X[:],'y':2}
>>> X[1] = 'two'              #这种话X做的不论什么改动仅仅会影响自身
>>> L,D
(['a', [1, 2, 3], 'b'], {'y': 2, 'x': [1, 2, 3]})

#拷贝须要注意的是: 无条件值的分片以及字典copy方法仅仅能做顶层复制。假设须要一个深层次嵌套的数据结构的完整的,全然独立的数据结构。须要用copy模块 X = copy.deepcopy(Y) 能递归地遍历对象来复制它们全部的组成部分。这样的情况比較少见,一般来说copy就能够了。

类型測试

>>> isinstance([1],list)       #一般建议使用此种类型做类型測试
True
>>> type([1]) == list
True
>>> type([1]) == type([])
True

反复添加层次深度

>>> L = [7,8]
>>> X = L*2
>>> Y = [L]*2
>>> X;Y
[7, 8, 7, 8]
[[7, 8], [7, 8]]
>>> L[0]=1         #改动列表中某个元素的值
>>> X;Y            #Y的值会发生改变
[7, 8, 7, 8]
[[1, 8], [1, 8]]


>>> X = L[:]*2     #拷贝
>>> Y = [L[:]]*2
>>> X;Y            #值都不变
[7, 8, 7, 8]
[[7, 8], [7, 8]]

不可变类型不能够在原处改动

>>> T = (1,2,3)
>>> T[2] = 4      #报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> T = T[:2] + (4,) #但能够通过切片。合并等方法来处理
>>> T
(1, 2, 4)

优点是: 当程序处理元祖时,不会报上面的错,而影响程序执行.


L[:0] 为空 ''  


程序一些规则

1. 最好四个空格

2. if (x>y): print x   #()最好不要用,这是类C语言风格

3. a = 1; b = 2; print a+b;  #最好不用分号;

3. 跨越多行最好用以下这几种方式(){}[],不要用从程序的可读性来说:

>>> if (A == 1 and
...     B == 2 and
...     C == 3):
...   print 'spam'*3
...
spamspamspam

>>> mylist = [1,
...           2,
...           3,
...           4]
>>> mylist

#虽然这样的方式也支持,可维护性差也非常脆弱

>>> A,B,C,D = 1,2,3,4
>>> X = A + B +      #这是一种类似于C语言的风格,最好不用
...     C + D
>>>
>>> X
10


在Python中else能够和if结合,也能够和try,while,for来结合使用.

#多行放一行,必须有;作为语句结尾

#且仅仅能是简单语句:比方说赋值语句,打印和函数调用

>>> x,y,z = 1,2,3; total(x,y,z)
4
>>> a = 1; b = 2; print a + b
3

Python中经常使用赋值语句

>>> spam = 'SPAM'               #基本形式
>>> spam,ham = 'SPAM','HAM'     #元祖赋值运算
>>> [spam,ham] = ['SPAM','HAM']  #列表赋值运算

#注意下这样的赋值方式,比較新颖与特殊

>>> L = [1,2,3,4]
>>> L[len(L):] = [5,6]  
>>> L
[1, 2, 3, 4, 5, 6]
>>> a,b,c,d    = 'SPAM'          #列表赋值运算,通用性, a='S',b='P'...
>>> spam = ham = 'lunch'        #多目标赋值运算

相当于以下:

>>> a = 'SPAM'
>>> b = a
>>> c = b

多目标赋值注意共享引用问题

#为整数

>>> a = b = 0   
>>> b +=1
>>> a,b
(0, 1)

#为列表

>>> a = b = []  
>>> b.append(4)
>>> a,b
([4], [4])

#其矫正

>>> a = []
>>> b = []
>>> b.append(4)
>>> a,b
([], [4])
>>> spams += 42                 #增强赋值运算spam=spam+42,输入少,运行速度快

有三个长处:

1. 程序猿输入降低

2. 左側仅仅计算一次: 假设是X是复杂的对象表达式

X +=Y        X仅仅计算一次

X  = X + Y   X必须计算两次,因此前者更快些

3. 优化技术会自己主动选择.对于支持原地运算的对象(比方说:列表),增强形式会自己主动运行原处改动的运算,而不是速度更慢的复制操作.
>>> X,Y = Y,X                   #X,Y值颠倒

>>> red,green,blue = range(3)   #序列分解赋值red =1,green =2,blue =3
>>> red,yellow
(0, 3)

以下是序列分解赋值简单样例,将其分解为開始和结尾两部分

>>> L = range(10)
>>> while L:
...   front,L = L[0],L[1:]
...   print front,L
...
0 [1, 2, 3, 4, 5, 6, 7, 8, 9]
1 [2, 3, 4, 5, 6, 7, 8, 9]
2 [3, 4, 5, 6, 7, 8, 9]
3 [4, 5, 6, 7, 8, 9]
4 [5, 6, 7, 8, 9]
5 [6, 7, 8, 9]
6 [7, 8, 9]
7 [8, 9]
8 [9]
9 []

增强赋值及共享引用

>>> M = [1,2]
>>> L = M
>>> M = M + [3,4] #'+'复制新对象
>>> M,L           #所以仅仅有M改变,L不变
([1, 2, 3, 4], [1, 2])


>>> M = [1,2]
>>> L = M
>>> M += [3,4]    #+="在总是在原处在修改
>>> M;L           #所以ML都发生了改变
[1, 2, 3, 4]
[1, 2, 3, 4]

变量名命名规则

以_或字母开头,后面接[a-zA-Z],[0-9],_

所以以下是正确的

_spam

Spam_

spam1

以下是错误的

1spam

spam$

@#!

还要注意。不要用Python保留字,特别是在模块中,如我们能够给脚本取名and.py, my-file.py但确不能够作为包导入

>>> import and
SyntaxError: invalid syntax
>>> import my-file
SyntaxError: invalid syntax

命令惯例

_X       不会被from module import * 导入

__X__    系统定义的变量名,对解释器有特殊意义

__X      是类的本地变量,不能被外界訪问

通过交互模式执行时,_X会保留最后表达式的结果

其它规则

1. 类名。首字母大写

2. 模块名小写

3. 函数名首字母小写


A < B and B !=C

A < B < C  等价于 A < B and B < C

=   表达式赋值

==  測试是否相等

表达式在原地改动

#正确的做法例如以下:

>>> L = [1,2]
>>> L.append(3)
>>> L
[1, 2, 3]

#错误的做法例如以下:

>>> L = L.append(4)  #将原地加入的值再赋给L
>>> L                #空值
>>> 

对列表调用append,sort或者reverse这类在原处改动的运算,一定是对列表做原处的改动。但这些方法在列表改动后并不会把列表返回。其实,它们返回的是None对象。假设赋值给该变量的变量名。仅仅会丢失该列表。并且可能在此过程中被当成垃圾回收。这是刚開始学习的人常犯的错误。所以不要这么做。

Print

#sys.stdout.write具有相同的作用

>>> import sys
>>> sys.stdout.write('Hello,World!')
Hello,World!

print spam,ham             #把对象打印至sys.stdout,在元素间添加一个空格,在末尾添加换行字符

print spam,ham,            #如上。但在文本末尾没有加换行符号,想显示连续输出的效果,非常实用

print >> myfile,spam,ham   #把文字传给myfile.write,而不是sys.stdout.write

>>> for i in range(4):
print i
输出结果
0
1
2
3
>>> for i in range(4):
print i,
输出结果
0 1 2 3  #输出默认有个空格

>>> myfile = file('myfile.txt','w')
>>> say    = 'This is print >> test!'
>>> print >> myfile, say               #将say中内容传给
>>> myfile.close()

print 和 sys.stdout关系例如以下:

print X

等价于

import sys

sys.stdout.write(str(X)+' ')

print >> file扩展

通过赋值sys.stdout而将打印文字重定向的技巧,在实际上很经常使用。

sys.stdout是个普通的文件对象,能够存储它,须要时恢复了。看以下的样例.

>>> import sys
>>> temp = sys.stdout                #存储到暂时变量
>>> sys.stdout = open('log.txt','a') #重定向到一个文件
>>> print 'spam'                     #向文件里打印,而不是在屏幕上显示
>>> print 1,2,3
>>> sys.stdout.close()               #将输出结果从内存写入硬盘
>>> print 'back here'                #所以这里会报错
Traceback (most recent call last):
  File "<pyshell#39>", line 1, in <module>
    print 'back here'
ValueError: I/O operation on closed file
>>> sys.stdout = temp                #恢复原始流          
>>> print 'back here'                #又一次再屏幕上显示输出
back here
>>> print open('log.txt').read()     #早期的打印结果
spam
1 2 3

鉴于这样的手动保存和恢复原始输出流的方法比較复杂,增强print的扩展功能.

log = open('log.txt','a')

print >> log,x, y, z    #Print to a file-like object

print a, b, c           #Print to original stdout

>>> log = open('log.txt','a')
>>> print >> log, 1, 2, 3
>>> print >> log, 4, 5, 6
>>> log.close()
>>> print 7,8,9
7 8 9
>>> print open('log.txt').read()
1 2 3
4 5 6


这样的print的扩展形式通经常使用于将错误打印信息到标准错误流sys.stderr,有两种方式

方法一:

>>> import sys
>>> sys.stderr.write(('Error info:...')+' ')
Error info:...

方法二:
>>> print >> sys.stderr, 'Error info:...'
Error info:...


while:

x = 'spam'

while x:   #while x not empty

#等价于 while x !='' 

  print x,

  x = x[1:]

【DocStings规范

文档字符串的惯例是一个多行字符串,它的首行以大写字母開始,句号结尾。

第二行是空行,

从第三行開始是具体的描写叙述。

.__doc__来读取出来,比方:

def printMax(x,y):
    '''Print the max of the two integrate.

       So the two values should be integrate'''
    x = int(x)
    y = int(y)

    if x > y:
        print 'The Max is:', x
    elif y > x:
        print 'The Max is:', y
    else:
        print 'x == y'

print printMax(1,4)
print printMax.__doc__

也能够用帮助信息将其打印出来

>>> help(printMax)
Help on function printMax in module __main__:

printMax(x, y)
    Print the max of the two integrate.
    
    So the two values should be integrate
三种布尔运算

if X and Y:  假设X和Y都为真。方为真

if X or  Y:  假设X或Y为真。就是真

if not X  :  假设X为假。那就是真(表达式返回True或False)

if/else 三元表达式

Variable = A if expression else B

变量赋值: 假设条件为真的话。那么为A。条件为假的话,B

>>> a = 10
>>> b = 20
>>> V = b if b > 10 else a
>>> V
20

A = [Z,Y][bool(X)]

>>> ['f','t'][bool('')]     #bool('')返回0,所以取前面一个
'f'
>>> ['f','t'][bool('true')] #bool('true')返回1,所以取后面一个
't'

【短路

在程序中,为防止短路现象(前面条件满足了,后面就不运行),将其赋值给暂时变量

temp1,temp2 = f1(),f2()

if temp1 or temp2: ...

break,continue,pass,和循环else

break:      跳出近期所在的循环(跳过整个循环语句)

continue:   跳到近期所在的循环的开头处(来到循环的首行) 

pass:       什么事也不干,占位语句,有时也用于将来补齐代码

循环else块: 仅仅有当循环正常离开时才会运行(也就是没有碰到break语句).

在for循环中元祖赋值

>>> T =((1,2),(3,4),(5,6),(7,8))
>>> for (a,b) in T:
...   print a,b
...
1 2
3 4
5 6
7 8

嵌套for循环

items = [2,'Spam',{'a':1},(4,5),[1,2],((4,5),(7,8))] #要找的目标
tests = [(4,5),3.14]                                 #測试对象

for key in tests:                                    #遍历全部的test
    for item in items:                               #遍历全部的item
        if key == item:
            print key,'has found!'
            break
        else:
            print key,'not Found!'

简单点写

for key in tests:
    if key in items:
        print key, 'has found!'
    else:
        print key, 'not found!'

输出结果:

>>> 
(4, 5) has found!
3.14 not found!

求交集

seq1 = 'spam'
seq2 = 'scam'
res  = []

for x in seq2:
    if x in seq1:
        res.append(x)
        
print res

输出结果

['s', 'a', 'm']

【迭代工具

for循环可用于不论什么可迭代工具. 可迭代工具一般包括for循环,列表解析,in成员測试,map等内置工具

以下这样的方式相比較for循环迭代,速度会慢一些,由于迭代器在Python中是以C语言的速度执行的,而while循环是Python虚拟机执行Python字节码的.所以不论什么时候,我们把Python代码换成C代码,速度都会快些.for循环一般比while循环easy些。速度更快些.

>>> while True:
...   line = f.readline()
...   if not line: break
...   print line.upper()


对字典迭代更简洁,高效的方法

D = {'a':1,'b':2,'c':3}

>>> for key in D:
...   print key,D[key]
...
a 1
c 3
b 2

其它迭代工具

每一种由左往右扫描对象的工具都会使用迭代协议,包含for循环,列表解析,in成员測试,map函数,及其它内置工具(sort,sum等)

#假如測试文件test.txt就以下两行

This is line 1
This is line 2

>>> uppers = [line.upper() for line in open('test.txt')]
>>> uppers
['THIS IS LINE 1 ', 'THIS IS LINE 2 ', ' ']

>>> 'This is line 2 ' in open('test.txt')
True

>>> sorted(open('test.txt'))
[' ', 'This is line 1 ', 'This is line 2 ']

>>> sorted([4,3,1,2])
[1, 2, 3, 4]
>>> sum([4,3,1,2])
10
>>> any(['spam','','ni'])  #返回True或者False
True
>>> all(['spam','','ni'])  #返回True或者False
False

包含list,tuple,及join方法,甚至赋值语句,都是可迭代对象

>>> list(open('test.txt'))
['This is line 1 ', 'This is line 2 ', ' ']
>>> tuple(open('test.txt'))
('This is line 1 ', 'This is line 2 ', ' ')
>>> '&&'.join(open('test.txt'))
'This is line 1 &&This is line 2 && '
>>> a,b,c = open('test.txt')
>>> a,b,c
('This is line 1 ', 'This is line 2 ', ' ')

range,xrange

range: 一次性将全部的索引放入列表

range支持反向迭代. 

>>> range(5,-5,-1)
[5, 4, 3, 2, 1, 0, -1, -2, -3, -4]

xrange: 没有速度优势,但假设有大数据,则有空间优势.在Python 3.0里面,xrange会消失,这一功能会放到range里面,range会变成迭代器对象,支持迭代协议,一次产生一个对象,而不是一次产生所有放到列表中.

>>> for i in range(3):
...   print '%06d' % (i),'Pythons'
...
000000 Pythons
000001 Pythons
000002 Pythons

简单的样例,假设要迭代,取出字符串中的每一个元素

方法一:  这样的应该是最简单的

>>> X = 'spam'
>>> for i in X:
...   print i,
...
s p a m

方法二:

>>> i = 0
>>> X = 'spam'
>>> while i < len(X):
...   print X[i],
...   i += 1
...
s p a m

方法三:

>>> X = 'spam'
>>> for i in range(len(X)):
...   print X[i],
...
s p a m

假设隔开来取,能够这样:

>>> S = 'ABCDEFGHIJK'
>>> for i in S[::2]:
...   print i,
...
A C E G I K

或者:

>>> S = 'ABCDEFGHIJK'
>>> for i in range(0,len(S),2):
...   print S[i],
...
A C E G I K

但假设要改动列表的话:

#第一种方法就不行了.

>>> L = [1,2,3,4]
>>> for x in L:
...   x += 1
...
>>> L
[1, 2, 3, 4]

#必须用另外一种方法

>>> L = [1,2,3,4]
>>> for i in range(len(L)):
...   L[i] +=1
...
>>> L
[2, 3, 4, 5]

#或者用第三种方法

>>> L = [1,2,3,4]
>>> i = 0
>>> while i < len(L):
...   L[i] += 1
...   i += 1
...
>>> L
[2, 3, 4, 5]

当然

[x+1 for x in [1,2,3,4]] 这样的列表解析更简单些

并行遍历,zip

内置的range同意我们在for循环中以非完备的方式遍历序列,内置的的zip函数也能够让我们使用for循环来并行使用多个序列,假如要计算两个坐标的和值

>>> L = [1,2,3]
>>> L1 = [1,2,3]
>>> L2 = [4,5,6]
>>> zip(L1,L2)           #使用zip创建配对后的元祖列表
[(1, 4), (2, 5), (3, 6)]
>>> for (x,y) in zip(L1,L2):
...   print x,y,'==>',x+y
...
1 4 ==> 5
2 5 ==> 7
3 6 ==> 9

#ZIP函数支持两个以上的參数

>>> T1,T2,T3 = (1,2),(3,4),(5,6)
>>> zip(T1,T2,T3)
[(1, 3, 5), (2, 4, 6)]

#并且以最小长度的为准.

>>> S1 = 'ABC'
>>> S2 = 'XYZ123' #123超过部分, 不在元祖队列
>>> zip(S1,S2)
[('A', 'X'), ('B', 'Y'), ('C', 'Z')]

ZIP创建字典

像以下这样一个字典

>>> D1 = {'spam':1,'eggs':3,'cake':5}
>>> D1
{'cake': 5, 'eggs': 3, 'spam': 1}

能够通过以下方式赋值来建立 

>>> D1 = {}
>>> D1['spam'] = 1
>>> D1['eggs'] = 3
>>> D1['cake'] = 5
>>> D1
{'cake': 5, 'eggs': 3, 'spam': 1}

假设是通过程序获得keys,values的列表,比方说

>>> keys = ['spam','eggs','cake']
>>> vals = [1     , 3    ,5     ]

那么要怎样建立字典呢,方法非常easy

方法一:

>>> D2 = {}
>>> for k,v in zip(keys,vals):
...   D2[k] = v
...
>>> D2
{'cake': 5, 'eggs': 3, 'spam': 1}

方法二:
>>> D3   = dict(zip(keys,vals))
>>> D3
{'cake': 5, 'eggs': 3, 'spam': 1}

产生偏移和元素:enumerate

一般做法:

>>> S = 'spam'
>>> offset = 0
>>> for item in S:
...   print item,'offset is:', offset
...   offset += 1
...
s offset is: 0
p offset is: 1
a offset is: 2
m offset is: 3

#enumerate函数实现

>>> S = 'spam'
>>> for (offset,item) in enumerate(S):   #注意offset,item顺序
...   print item,'appears in place', offset
...
s appears in place 0
p appears in place 1
a appears in place 2
m appears in place 3

#enumerate函数会自己主动产生迭代器,有next()方法,每次遍历时会产生(index,value)的元祖列表

>>> E = enumerate(S)
>>> E.next()
(0, 's')
>>> E.next()
(1, 'p')
>>> E.next()
(2, 'a')
>>> E.next()
(3, 'm')
>>> E.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

#又一个样例,结合列表解析, s*0,p*1,a*2...

>>> [c* i for (i,c) in enumerate(S)]
['', 'p', 'aa', 'mmm']

列表解析基础

假设要实如今[1,2,3,4]这个列表上每一个元素加10,能够这样

>>> L = [1,2,3,4]
>>> for i in range(len(L)):
...   L[i] += 10
...

>>> L
[11, 12, 13, 14]

或者

>>> L = [1,2,3,4]
>>> res = []
>>> for x in L:
...   res.append(x+10)
...
>>> res
[11, 12, 13, 14]

没有必要用列表解析,但列表解析有下面优点

[x+10 for x in [1,2,3,4]]

1. 代码简洁

2. 速度快,经常快2倍左右.由于列表解析的迭代在解释器上是以C语言的速度运行的,而不是手动编写的Python代码.


对文件使用列表解析

#常规做法,这样做,每一个后面会有换行符,挺碍事的.

>>> f = open('test.txt')
>>> lines = f.readlines()
>>> lines
['This is line 1 ', 'This is line 2 ']

#列表解析,能够这样做

>>> lines = [line.rstrip() for line in lines]
>>> lines
['This is line 1', 'This is line 2']

#设置能够不用中间变量,直接在open().readlines()写

>>> lines = [line.rstrip() for line in open('test.txt')]
>>> lines
['This is line 1', 'This is line 2']

NOTE: 对于大型文件,列表解析的速度尤其明显


【扩展列表解析语法】

列表解析中嵌套for循环再结合if语句来过滤条件,这是个很实用的扩展

假如要将test.txt文件里,首字母为P的

Python
Perl
Java
Shell

方法一: 常规做法

>>> f   = open('test.txt')
>>> res = []

>>> while True:
...   line = f.readline()
...   if not line: break
...   if line[0] == 'P':
...     res.append(line.rstrip())
...
>>> res
['Python', 'Perl']

或者

res = []

>>> for line in open('test.txt'):
...   if line[0] == 'P':
...     res.append(line.rstrip())
...
>>> res
['Python', 'Perl']

方法二: 列表解析

#仅仅须要一行代码

>>> lines = [line.rstrip() for line in open('test.txt') if line[0] == 'P']
>>> lines
['Python', 'Perl']


【dir函数】

dir函数: 抓取对象内全部属性的简单方法,

假设是须要导入的某个模块的话,能够这样使用.

>>> import sys
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__',......,'version_info', 'warnoptions', 'winver']

假设是系统某个类型的话,能够这样使用:

>>> dir(list)
['__add__', '__class__'..'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

>>> dir(dict)
['clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']

>>> dir(int)

>>> dir(str)

>>> dir(file)

>>> dir(tuple)

或者像以下这样也行

>>> dir(0)

>>> dir('')

>>> dir(open('test.txt'))

>>> dir({})

>>> dir([])

>>> dir(())


原文地址:https://www.cnblogs.com/gcczhongduan/p/5252897.html