python的基本知识(根据阅读python教程整理)
1.字符串
字符串可以切片,str[0:2] 相当于str[:2],str[0]不能更改字符串里的某个字符.字符串前面添加r可以包括转义字符。
链表:str=['aaa','bbb','ccc'],可以更改链表里的某个数据,可以是不同数据类型,也可以切片链表为可变序列。在迭代过程中修改迭代序列不安全(只有在使用链表这样的可变序列时才会有这样的情况)。如果你想要修改你迭代的序列(例如,复制选择项),你可以迭代它的复本。通常使用切片标识就可以很方便的做到这一点。
2.flow control
if elif else
for in
break 和 continue 语句, 以及循环中的 else 子句
break语句和C中的类似,用于跳出最近的一级for或while循环。
continue 语句是从C中借鉴来的,它表示循环继续执行下一次迭代。
循环可以有一个else子句;它在循环迭代完整个列表(对于for)或执行条件为false(对于while)时执行,但循环被break中止的情况下不会执行。
>>> for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0:
... print n, 'equals', x, '*', n/x
... break
... else:
... # loop fell through without finding a factor
... print n, 'is a prime number'
pass 语句什么也不做。
3.range()
如果你需要一个数值序列,内置函数range()可能会很有用,它生成一个等差级数链表。
需要迭代链表索引的话,如下所示结合使用range()和len():
>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
... print i, a[i]
...
0 Mary
1 had
2 a
3 little
4 lamb
语句result.append(b)称为链表对象result的一个方法(method)。
4.定义函数
1)
def functionname():
return语句从函数中返回一个值,不带表达式的return返回None。过程结束后也会返回None。
定义参数个数可变的函数
最有用的形式是给一个或多个参数指定默认值。
重要警告:默认值只会解析一次。当默认值是一个可变对象,诸如链表、字典或大部分类实例时,会产生一些差异。
2)参数关键字
函数可以通过参数关键字的形式来调用,形如“keyword = value”。
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
parrot(1000)
parrot(action = 'VOOOOOM', voltage = 1000000)
parrot('a thousand', state = 'pushing up the daisies')
通常,参数列表中的每一个关键字都必须来自于形式参数,每个参数都有对应的关键字。形式参数有没有默认值并不重要。实际参数不能一次赋多个值--形式参数不能在同一次调用中同时使用位置和关键字绑定值。
3)可变参数表
最后,一个最不常用的选择是可以让函数调用可变个数的参数。这些参数被包装进一个拓扑。在这些可变个数的参数之前,可以有零到多个普通的参数:
def fprintf(file, format, *args):
file.write(format % args)
parrot('a million', 'bereft of life', 'jump')
5.数据结构
1)堆栈
链表方法使得链表可以很方便的做为一个堆栈来使用,堆栈是这样的数据结构,最先进入的元素最后一个被释放(后进先出)。用 append() 方法可以把一个元素添加到堆栈顶。用不指定索引的 pop() 方法可以把一个元素从堆栈顶释放出来
2)队列
你也可以把链表当做队列使用,队列是这样的数据结构,最先进入的元素最先释放(先进先出)。使用
队列最后,以0为参数调用 pop() 方法可以把最先进入的元素释放出来。
3)函数化编程工具
对于链表来讲,有三个内置函数非常有用:filter(), map(), 和 reduce()。 append()方法可以把元素添加到
“filter(function, sequence)” 返回一个序列(sequence),包括了给定序列中所有调用function(item)后返回值为true的元素。(如果可能的话,会返回相同的类型)。
“map(function, sequence)” 为每一个元素依次调用 function(item) 并将返回值组成一个链表返回。
可以传入多个序列,函数也必须要有对应数量的参数,执行时会依次用各序列上对应的元素来调用函数(如果某些序列比其它的短,就用None来代替)。如果把None做为一个函数传入,则直接返回参数做为替代。
组合这两种情况,我们会发现“map(None, list1, list2)”是把一对序列变成元素对序列的便捷方式。
"reduce(func, sequence)" 返回一个单值,它是这样构造的:首先以序列的前两个元素调用函数,再以返回值和第三个参数调用,依次执行下去。
可以传入第三个参数做为初始值。如果序列是空的,就返回初始值,否则函数会先接收初始值和序列的第一个元素,然后是返回值和下一个元素,依此类推。
>>> def sum(seq):
... def add(x,y): return x+y
... return reduce(add, seq, 0)
...
>>> sum(range(1, 11))
55
>>> sum([])
0
不要像示例中这样定义 sum():因为合计数值是一个通用的需求,在新的2.3版中,提供了内置的 sum(sequence) 函数。
4)链表推导式
链表推导式提供了一个创建链表的简单途径,无需使用 map(), filter() 以及 lambda。返回链表的定义通常要比创建这些链表更清晰。每一个链表推导式包括在一个for语句之后的表达式,零或多个for或if语句。返回值是由for或if子句之后的表达式得到的元素组成的链表。如果想要得到一个元组,必须要加上括号。
>>> vec = [2, 4, 6]
>>> [3*x for x in vec]
[6, 12, 18]
>>> [3*x for x in vec if x > 3]
[12, 18]
5)del 语句
有一个方法可从链表中删除指定索引的元素:del语句。这个方法也可以从链表中删除切片(之前我们是把一个空链表赋给切片)。
6)元组(Tuples)和序列(Sequences )
我们知道链表和字符串有很多通用的属性,例如索引和切片操作。它们是序列类型中的两种。因为Python是一个在不停进化的语言,也可以加入其它的序列类型,这里有另一种标准序列类型:元组。
一个元组由数个逗号分隔的值组成,元组就像字符串,不可改变:不能给元组的一个独立的元素赋值(尽管你可以通过联接和切片来模仿)。也可以通过包含可变对象来创建元组,例如链表。
语句 t = 12345, 54321, 'hello!' 是元组封装(sequence packing)的一个例子:值 12345, 54321 和 'hello!' 被封装进元组。其逆操作可能是这样:
>>> x, y, z = t
这个调用被称为序列拆封非常合适。序列拆封要求左侧的变量数目与序列的元素个数相同。要注意的是可变参数(multiple assignment
)其实只是元组封装和序列拆封的一个结合!
这里有一点不对称:封装多重参数通常会创建一个元组,而拆封操作可以作用于任何序列。
7) 字典(Dictionaries)
理解字典的最佳方式是把它看做无序的关键字:值对( key:value pairs )集合,关键字必须是互不相同的(在同一个字典之内)。一对大括号创建一个空的字典:{}。初始化链表时,在大括号内放置一组逗号分隔的关键字:值对,这也是字典输出的方式。
字典的主要操作是依据关键字来存储和析取值。也可以用del来删除关键字:值对。如果你用一个已经存在的关键字存储值,以前为该关键字分配的值就会被遗忘。试图析取从一个不存在的关键字中读取值会导致错误。
字典的keys() 方法返回由所有关键字组成的链表,该链表的顺序不定(如果你需要它有序,只能调用关键字链表的sort()方法)。使用字典的 has_key() 方法可以检查字典中是否存在某一关键字。
表中存储关键字-值对元组的话,字典可以从中直接构造。关键字-值对来自一个模式时,可以用链表推导式简单的表达关键字-值链表。
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}
>>> dict([(x, x**2) for x in vec]) # use a list comprehension
{2: 4, 4: 16, 6: 36}
8)循环技巧
在字典中循环时,关键字和对应的值可以使用 items() 方法同时解读出来。
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
... print k, v
...
gallahad the pure
robin the brave
在序列中循环时,索引位置和对应值可以使用 enumerate() 函数同时得到。
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print i, v
...
0 tic
1 tac
2 toe
同时循环两个或更多的序列,可以使用 zip() 整体解读。
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
... print 'What is your %s? It is %s.' % (q, a)
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
6.深入条件控制
用于while和if语句的条件包括了比较之外的操作符。
in和not比较操作符审核值是否在一个区间之内。操作符is和is not比较两个对象是否相同;这只和诸如链表这样的可变对象有关。所有的比较操作符具有相同的优先级,低于所有的数值操作。
比较操作可以传递。例如 a < b == c 审核是否a小于b并b等于c。
比较操作可以通过逻辑操作符and和or组合,比较的结果可以用not来取反义。这些操作符的优先级又低于比较操作符,在它们之中,not具有最高的优先级,or的优先组最低,所以A and not B or C 等于 (A and (not B)) or C。当然,表达式可以用期望的方式表示。
逻辑操作符and 和or 也称作短路操作符:它们的参数从左向右解析,一旦结果可以确定就停止。例如,如果A和C为真而B为假,A and B and C 不会解析C。作用于一个普通的非逻辑值时,短路操作符的返回值通常是最后一个变量。
可以把比较或其它逻辑表达式的返回值赋给一个变量,例如:
7.模块
模块是包括Python定义和声明的文件。文件名就是模块名加上.py后缀。模块的模块名(做为一个字符串)可以由全局变量__name__得到。
如果你想要直接调用函数,通常可以给它赋一个本地名称:
import语句的一个变体直接从被导入的模块中导入命名到本模块的语义表中。例如:
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
这样不会从局域语义表中导入模块名(例如,fibo没有定义)。
这里还有一个变体从模块定义中导入所有命名:
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
这样可以导入所有除了以下划线(_)开头的命名。
1)模块搜索路径
导入一个叫spam的模块时,解释器先在当前目录中搜索名为spam.py的文件,然后在环境变量PYTHONPATH指琮的目录列表中搜索,然后是环境变量PATH中的路径列表。如果PYTHONPATH没有设置,或者文件没有找到,接下来搜索安装目录,在UNIX中,通常是 .:/usr/local/lib/python。
编译.pyc and .pyo文件
来自.pyc文件或.pyo文件中的程序不会比来自.py文件的运行更快;.pyc或.pyo文件只是在它们加载的时候更快一些。
变量sys.path 是解释器模块搜索路径的字符串列表。它由环境变量PYTHONPATH初始化,如果PYTHONPATH没有内定,就由内置的默认值初始化。你可以用标准和字符串操作修改它:
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')
dir
内置函数dir()用于按模块名搜索模块定义,它返回一个字符串类型的存储列表:
无参数调用时,dir()函数返回你当前定义的名称:
应该该列表列出了所有类型的名称:变量,模块,函数,等等:
dir()不会列出内置函数和变量名。如果你想列出这此内容,它们在标准模块__buildin__中定义:
>>> import __builtin__
>>> dir(__builtin__)
函数str() 用于将值转化为适于人阅读的形式,而 repr()转化为供解释器读取的形式(如果没有等价的语法,则会发生SyntaxError 异常) 某对象没有适于人阅读的解释形式的话,str()会返回与repr()等同的值。
7.文件操作
open() 返回一个文件对象 ,通常的用法需要两个参数:“open(filename, mode)”。
>>> f=open('/tmp/workfile', 'w')
读取文件内容,需要调用 f.read(size),该方法读取若干数量的数据并以字符串形式返回其内容,字符串长度为数值size所指定的大小。如果没有指定size或者指定为负数,就会读取并返回整个文件。当文件大小为当前机器内存两倍时,就会产生问题。正常情况下,会按size尽可能大的读取和返回数据。如果到了文件末尾,f.read() 会返回一个空字符串("")。
>>> f.read()
.readline() 从文件中读取单独一行,字符串结尾会自动加上一个换行符,只有当文件最后一行没有以换行符结尾时,这一操作才会被忽略。这样返回值就不会有什么混淆不清,如果 if f.readline() 返回一个空字符串,那就表示到达了文件末尾,如果是一个空行,就会描述为‘/n’,一个只包含换行符的字符串。
f.readlines() 返回一个列表,其中包含了文件中所有的数据行。如果给定了 sizehint 参数,就会读入多于一行的比特数,从中返回行列表。这个功能通常用于高效读取大型行文件,避免了将整个文件读入内存。这种操作只返回完整的行。
f.write(string) 将 string 的内容写入文件,返回None。
f.tell() 返回一个整数,代表文件对象在文件中的指针位置,该数值计量了自文件开头到指针处的比特数。需要改变文件对象指针话话,使用“f.seek(offset, from_what)” 。指针在该操作中从指定的引用位置移动 offset 比特,引用位置由 from_what 参数指定。. from_what 值为0表示自文件起初处开始,1表示自当前文件指针位置开始,2表示自文件末尾开始。 from_what 可以乎略,其默认值为零,此时从文件头开始。
文件使用完后,调用 f.close() 可以关闭文件,释放打开文件后占用的系统资源。调用 f.close()之后,再调用文件对象会自动引发错误。
8.对象持久化pickle
Python提供了一个名为 Pickle 的标准模块。这是一个令人赞叹的模块,几乎可以把任何Python对象(甚至是一些Python代码块(form)!)表达为为字符串,这一过程称之为封装 (pickling)。从字符串表达出重新构造对象称之为拆封(unpickling)。封装状态中的对象可以存储在文件或对象中,也可以通过网络在远程的机器之间传输。
如果你有一个对象x,一个以写模式打开的文件对象f,封装对像的最简单的方法只需要一行代码:
pickle.dump(x, f)
如果f是一个以读模式打开的文件对象,就可以重装拆封这个对象:
x = pickle.load(f)
(如果不想把封装的数据写入文件,这里还有一些其它的变化可用。完整的pickle文档请见库参考手册)。
pickle 是存储Python对象以供其它程序或其本身以后调用的标准方法。提供这一组技术的是一个持久化对象( persistent object )。因为 pickle 的用途很广泛,很多Python扩展的作者都非常注意类似矩阵这样的新数据类型是否适合封装和拆封。
9.异常处理
try 语句按如下方式工作:
首先,执行 try 子句(在try 和 except关键字之间的部分)。
如果没有异常发生,except 子句 在try语句执行完毕后就被忽略了。
如果在try子句执行过程中发生了异常,那么该子句其余的部分就会被忽略。如果异常匹配于except关键字后面指定的异常类型,就执行对应的except子句,忽略try子句的其它部分。然后继续执行try语句之后的代码。
如果发生了一个异常,在except子句中没有与之匹配的分支,它就会传递到上一级try语句中。如果最终仍找不到对应的处理语句,它就成为一个未处理异常,终止程序运行,显示提示信息。
一个try 语句可能包含多个 except 子句,分别指定处理不同的异常。至多只会有一个分支被执行。异常处理程序只会处理对应的try子句中发生的异常,在同一个try语句中,其他子句中发生的异常则不作处理。一个except子句可以在括号中列出多个异常的名字,
最后一个except子句可以省略异常名,把它当做一个通配项使用。一定要慎用这种方法,因为它很可能会屏蔽掉真正的程序错误,使人无法发现!它也可以用于打印一行错误信息,然后重新抛出异常(可以使调用者更好的处理异常)。
try ... except 语句可以带有一个 else 子句, 该子句只能出现在所有except子句之后。当try语句没有抛出异常时,需要执行一些代码,可以使用这个子句。
使用 else 子句比在 try 子句中附加代码要好,因为这样可以避免 try ... except 意外的截获本来不属于它们保护的那些代码抛出的异常。
发生异常时,可能会有一个附属值,作为异常的参数存在。这个参数是否存在、是什么类型,依赖于异常的类型。
在异常名(列表)之后,也可以为 except 子句指定一个变量。这个变量绑定于一个异常实例,它存储在 instance.args 的参数中。为了方便起见,异常实例定义了 __getitem__ 和 __str__ ,这样就可以直接访问过打印参数而不必引用 .args。
在发生了特定的异常时,程序员可以用 raise 语句强制抛出异常。例如:
>>> raise NameError, 'HiThere'
Traceback (most recent call last):
File "", line 1, in ?
NameError: HiThere
第一个参数指定了所抛出异常的名称,第二个指定了异常的参数。
如果你决定抛出一个异常而不处理它,raise 语句可以让你很简单的重新抛出该异常。
在程序中可以通过创建新的异常类型来命名自己的异常。异常类通常应该直接或间接的从 Exception 类派生
异常类中可以定义任何其它类中可以定义的东西,但是通常为了保持简单,只在其中加入几个属性信息,以供异常处理句柄提取。如果一个新创建的模块中需要抛出几种不同的错误时,一个通常的作法是为该模块定义一个异常基类,然后针对不同的错误类型派生出对应的异常子类。
try 语句还有另一个可选的子句,目的在于定义在任何情况下都一定要执行的功能。例如:
>>> try:
... raise KeyboardInterrupt
... finally:
... print 'Goodbye, world!'
不管try子句中有没有发生异常, finally 子句都一定会被执行。如果发生异常,在finally子句执行完后它会被重新抛出。 try 子句经由 break 或 return 退出也一样会执行finally 子句。
在finally 子句中的代码用于释放外部资源(例如文件或网络连接),不管这些资源是否已经成功利用。
在 try 语句中可以使用若干个 except 子句或一个 finally 子句,但两者不能共存。
10.私有变量
Python对类的私有成员提供了有限的支持。任何形如__spam (以至少双下划线开头,至多单下划线结尾)随即都被替代为 _classname__spam,去掉前导下划线的classname 即当前的类名。这种混淆不关心标识符的语法位置,所以可用来定义私有类实例和类变量、方法,以及全局变量,甚至于将其它类的实例保存为私有变量。
11.迭代器
这种形式的访问清晰、简洁、方便。这种迭代器的用法在Python中普遍而且统一。在后台,for 语句在容器对象中调用 iter() 。 该函数返回一个定义了 next() 方法的迭代器对象,它在容器中逐一访问元素。没有后续的元素时,next() 抛出一个 StopIteration 异常通知 for 语句循环结束。
了解了迭代器协议的后台机制,就可以很容易的给自己的类添加迭代器行为。定义一个 __iter__() 方法,使其返回一个带有 next() 方法的对象。如果这个类已经定义了 next(),那么 __iter__() 只需要返回self:
>>> class Reverse:
"Iterator for looping over a sequence backwards"
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def next(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
>>> for char in Reverse('spam'):
print char
12 发生器
发生器是创建迭代器的简单而强大的工具。它们写起来就像是正则函数,需要返回数据的时候使用yield 语句。每次 next() 被调用时,生成器回复它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)。以下示例演示了发生器可以很简单的创建出来:
>>> def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse('golf'):
print char
f
l
o
g
前一节中描述了基于类的迭代器,它能作的每一件事发生器也能作到。因为自动创建了 __iter__() 和 next() 方法,发生器显得如此简洁。
另外一个关键的功能是两次调用之间的局部变量和执行情况都自动保存了下来。这样函数编写起来就比手动调用 self.index 和 self.data 这样的类变量容易的多。
除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出 StopIteration异常。综上所述,这些功能使得编写一个正则函数成为创建迭代器的最简单方法。