我以前只系统地看过Python的菜鸟教程,而菜鸟教程中只介绍了最基本的语法知识 在实际用Python的时候发现自己掌握的语法知识远远不够,现在开始看 Python 核心编程(第二版),希望对Python有个更深入的理解。
第二章
乘方操作符
2 ** 3 = 8
for循环遍历
发现有的人喜欢在遍历列表的时候,不仅遍历列表的元素,同时还得到相应的索引,这时就可以使用 enumerate函数
for i,ch in enumerate(foo):
print ch,'(%d)'%i
结果:
a(0)
b(1)
c(2)
错误和异常
try:
fielname = 'test.txt'
fobj = open(filename,'r')
fobj.close()
except IOError,e:
print 'file open error',e
函数的默认参数
def foo(debug = True):
if debug:
print 'Hello World'
print 'done'
第三章
同一行书写多个语句
import sys; x = 'foo' ;
增量赋值
但是不支持 x++ 或 ++x 这种前置/后置 自增/自减 运算符
x += 1
多重赋值
x = y = z = 1 # 结果就是 x = 1,y = 1,z = 1
多元赋值
x,y,z = 1,2,'string'
x,y = y,x # 方便地交换变量值
缩进
缩进的上下边界为 3 个空格 和 7 个空格
模块结构和布局
每个 python 脚本文档应该有清晰的结构,推荐结构如下:
- 起始行,通常只在类 Unix 环境下使用,有起始行就能够仅输入脚本名字来执行脚本,无需直接调用解释器。
- 模块文档,介绍模块的功能和重要全局变量的含义,模块外可以通过 module.doc 来访问,使用 help() 查阅模块功能的时候,也是显示的这些内容。
"this is a test module"
- 模块导入语句
- 变量定义
- 类定义语句,类功能描述和模块功能描述相似,通过 class.doc 访问
- 函数定义语句,函数功能描述和模块功能描述相似,通过 function.doc 访问
- 主程序
__name__ == ‘__main__’
一般在每个模块文件的主程序位置都要加这样一个判断,表示只有该文件作为主程序运行时才会执行以下代码,否则作为模块导入文件的时候是不会执行的。
我们完成了每个模块之后可以在这个位置书写模块的测试代码。
垃圾收集
python 和 java 类似,也是全权负责内存的管理,其中垃圾内存管理,使用变量的引用计数来作为指标,引用次数不大于 0,那么就将变量所占内存回收。
- 增加引用计数
x = 3.14 y = x # x 的引用次数加 1
- 减少引用次数
- 本地引用离开了作用范围
- 对象的一个别名被赋值给其他对象
- 对象被从一个窗口中移除
myList.remove(x)
- 窗口对象被删除
del myList # myList中的子元素跟着被删除
- 对象被显式地删除
del x
- 循环引用:使用循环垃圾收集器
x = 123
y = x
x = y # x 和 y 发生了循环引用,x 和 y 的引用次数无论如何最少为 1
为什么 Pyhthon 中不需要声明函数类型?
???
第四章 Python 对象
字符串比较
按照序列值,其实也就是 ASCII 值比较
is 和 == 的区别
实际上 a is b 操作等价于 id(a) == id(b)
a = 1
b = 1.0
a == b # True
a is b # False
type() 和 isinstance()
type()函数返回任意Python对象的类型,isinstance() 函数判断该对象是何种类型,书上举了这样的例子来说明 type() 和 isinstance()的用法。
num = -69
if isinstance(num,(int,long,float,complex)):
print type(num).__name__ # 输出 int
num = -5.2+1.9j
if isinstance(num,(int,long,float,complex)):
print type(num).__name__ # 输出 complex
type() 和 isinatance()帮助编程者保证调用的就是期望的对象或函数。
类型工厂函数
类似于 int()、type()、list()这些内置转换函数,调用这些函数的时候实际上是生成了该类的一个实例。 除了常见的之外,支持工厂函数的还有
frozenset()
classmethod()
staticmethod(0
super()
property()
file()
标准类型的分类
- 存储模型,分为容器类型(列表,元组等),原子模型(数值,字符串),主要区别就是是否可以包含多个值
- 更新模型,数值和字符串在被更新了之后,id(变量)的值会发生变化,即生成了一个新对象,而列表这种对象在被修改前后,id(变量)的值不变
- 访问模型,直接存取(非容器类型),顺序(列表),映射(字典)。
不支持的类型
- char 或 byte,可以用长度为 1 的字符串来表示
- 指针,python中没有必要使用指针,可以通过id()得到类似于地址的值,但是无法修改
- int short long,Python中的整形实现相当于 c 语言中的长整型
- float vs double,python的浮点类型是 c 语言中的双精度浮点类型,对于精度要求比较高的,可以用 decimal 类型
第五章 数字
int(), round(), floor() 的区别
- int: 直接去除小数部分
- round : 四舍五入
- floor : 找到不大于该数字的最小整数
// 和 /
- //:地板除
- / : 2.7之后的版本全都是真除法,2.7之前的,对float类型是真除法,对整形是地板除
ord() 和 chr()
- ord(): 获取 ASCII 码值
- chr(): 获取 ASCII 码值对应的符号
做笔试题的时候可能会用到
第六章 序列:字符串、列表和元组
连接操作符 +
重复操作 *
切片操作
sequence[index]
- index <0:表示以序列的结束为起点
ns = [1,2,3] print ns[-2] # 输出 2
- 返回一系列值
sequence[starting_index : ending_index]
如果
starting_index = 0
,starting_index
可以省略sequence[:ending_index]
同理如果
ending_index = len(sequence)-1
,ending_index
也可以省略sequence[2:]
如果
ending_index < 0
,终点就是len(sequence) + ending_index
ns = [1,2,3] print ns[:-1] # 输出 1,2
返回整个序列
sequence[:]
- 使用步长
sequence[starting_index : ending_index : step]
翻转操作
sequence[::-1] # 省略开始结束索引,步长为 -1
开始和结束索引可以超过序列的长度,开始索引小于0按0算,结束索引超过最大索引按最大索引算
字符串类型不可变
修改字符串中的某个字符,不能通过索引的方式来修改,只能通过创建一个新串。删除字符串中的某个字符也是一样。
编译时字符串连接
可以使用几个字符串连在一起来构建新字符串
foo = "Hello" "World" # "HelloWorld"
通过这种方法,可以把长的字符串分成几部分来写,让添加注释更方便
f = urllib.urlopen( 'http://' #protocol
... 'locahost' #hostname
... ':8000' #port
... '/cgi-bin/friends2.py') #file
# 其实就是一个完整的url
python 中所有对象都具有一个字符串表示,通过 rpr()和 tr()得到
print语句会自动为每个对象调用 str()
字符串模板
python相比较于格式化更强的字符串模板
from string import Template
s = Template('There are ${howmany} ${lang} Quotaion Symbols')
print s.substitute(lang = 'Python',howmany=3)
# There are 3 Python Quotaion Symbols
原始字符串 r
忽视转义字符
print r'\n' # 输出:\n
zip()
将两个字符串相应位置字符组合成一个
s,t = 'foa','obr'
zip(s,t)
# [('f', 'o'), ('o', 'b'), ('a', 'r')]
'''
应对特殊符号,比如 HTML 文本
列表赋值
切片更新列表
a = [1,2,3,4,5]
a[1:3] = a[3:5] # a = [1,4,5,4,5]
删除列表元素
已知索引
del aList[1]
不知索引,只知元素
aList.remove('hh')
# 如果有重名元素,那么按顺序删除第一个
已知索引,删除并返回该被删除对象
aList.pop()
连接操作符 +
a = a + b
’+’ 操作符是将 a,b 两个列表重新组合成一个新的列表,然后赋值给 a,a 已经不再是原来的那个列表
a.extend(b)
使用extend(),将 b 添加到了 a 的尾部,a 没有发生变化
列表解析
[ i*2 for i in [1,2,3]] # 输出 [1,4,9]
还可以带有判断
[i for i in range(8) if i%2 == 0] # 输出 [0,2,4,6]
内建函数之 sorted() 和 reversed()
返回一个新的列表,而使用 aList.sort(),是就地排序
列表内建函数
list.count(obj) # 返回对象 obj 在列表中出现的次数
list.index(obj,i,j) # 在列表索引i 到 j之间,返回 list[k] = obj 的元素的索引 k
list.insert(index,obj) # 向列表的 index 处添加元素 obj
list.sort(func=None,key = None,reverse = False) # func是比较函数,key是func的参数,reverse = True,递减
使用列表构建栈和队列
- 构建栈
aList.pop() # 出栈 aList.append() # 入栈
- 构建队列
aList.pop(0) # 出队 aList.append(0) # 入队
元组的不可变性
元组不可变性和字符串的不可变性类似。
虽然元组元素(指id值)不可变,但是元组中的元素是可变对象的,还是可以改变元素的所包含的元素,例如
t = (['xyz',300],23,-102) # ['xyz',300]中的元素是可变的
元组定义时,括号非必须
s = '1','2','3' # 相当于 s = ('1','2','3')
单元素元组
a = ('xyz',) # 如果没有 ",",a 会被赋值成一个 "xyz" 字符串
拷贝 Python 对象,浅拷贝和深拷贝
- 浅拷贝 当创建了一个对象 a,并将 a 赋值给了 b,只是将 a 这个引用复制给了 b,修改 b 引用的对象时,也就是在修改 a 引用的对象。
- 深拷贝
使用 copy 模块的 copy.deepcopy()
import copy b = copy.deepcopy(a) # 深拷贝 b = copy.copy(a) # 浅拷贝
第七章 字典
创建字典
dict2 = {'name':'earth','port':80}
fdict = dict((['x',1],['y',2])) # {'y': 2, 'x': 1}
从 Python2.3 开始可以用fromkeys(),来创建所有键值相同的字典
ddict = {}.fromkeys(('x','y'),-1) # {'y': -1, 'x': -1}
# 当然第二个参数是可选的,如果不设置,则默认将所有键值设置为 None
遍历字典
从Python2.2开始,不必在使用keys()方法先获得键值列表,直接使用迭代器访问
for key in dict2:
print key,dict2[key]
判断字典中是某个键
has_key()方法(不推荐,将被放弃),使用 in 和 not in 操作符。
其中因为字典的键的不可变性,因此列表和其他字典不可以作为键
删除字典中的元素
del dict2['name'] # 删除键为'name'的条目
dict2.clear() # 删除 dict2 中所有的条目
del dict2 # 删除整个 dict2
dict2.pop('name') # 删除并返回键为 'name' 的条目
字典相比于列表
不支持拼接 和 重复
字典的比较
字典的长度——> 字典的键 ——> 字典的值
映射类型相关的函数
工厂函数被用来创建字典。可以传递一个容器对象作为参数。将容器对象中的组合转化成键和值。
>>> dict(zip(('x', 'y'), (1, 2)))
{'y': 2, 'x': 1}
>>> dict([['x', 1], ['y', 2]])
{'y': 2, 'x': 1}
>>> dict([('xy'[i-1], i) for i in range(1,3)])
{'y': 2, 'x': 1}
接受关键字或关键字参数字典
dict(x = 1,y = 2)
{'y':2,'x':1}
可以拷贝另一个字典
dict9 = dict(**dict8)
# 或者
dict9 = dict8.copy()
# 二者都是深度拷贝
映射类型内建方法
dict.upate(dict2) # 将字典 dict2 的 键-值对添加到字典 dict 中,添加dict中不存在的键值对,将dict和dict2同时存在的键值对,更新成dict2的值
键必须是可哈希的
可变类型不可以做键,比如列表,字典等,属于不变类型的元组就可以做键
集合类型的创建
集合类型只能使用工厂方法 set() 和 frozenset()来创建
更新集合
s.add('z') # 将 z 添加到集合中
s.update('pypi') # 将 'pypi' 更新到集合中,相当于做并
s.remove('z') # 删除
s -= set('pypi') # 做差运算
del s # 删除整个集合
集合类型操作符
-
联合 , z = s|t
z 包含了 t 和 s 所有的元素 - 交集 &
- 差集 -
- 对称分布 ^,两个集合不属于对方的值的集合,也就是异或操作
另外 <
和 >
可以用来判断集合之间的从属关系
混合集合类型操作
如果左边集合是可变集合,右边集合是不可变集合,那么结果是可变结合。位置相反,结果相反。
集合类型操作符(仅用于可变集合)
|=
&=
-=
^=
内建函数
- set()和 frozenset() set() 生成可变集合,frozenset() 生成不可变集合 参数必须是可以迭代的,比如字符串,字典,列表,元组
第八章 条件和循环
条件语句缩进解决了”悬挂 else” 问题
/* dangling-else in C */
if (balance > 0.00)
if (((balance - amt) > min_bal) && (atm_cashout() == 1))
printf("Here's your cash; please take all bills.\n");
else
printf("Your balance is zero or negative.\n");
上面的 else 语句会给人一种错觉,好像 else 是属于上面的 if 语句(其实是属于下面的 if)。而 python 的强制缩进就可以避免这种错觉。
使用字典来替代 switch 语句
python 中不支持 switch 语句,但是可以用字典来作为 switch 的替代品。
msgs = {'create': 'create item',
'delete': 'delete item',
'update': 'update item'}
default = 'invalid choice... try again!'
action = msgs.get(user.cmd, default) # 相当于 switch 做选择
条件表达式
X if C else Y,其中 X 和 Y 是两个待选的值,如果表达式 C 为 True,返回 X,否则返回 Y
for 语句
for语句可以遍历序列成员,可以用在列表解析 和 生成器表达式中,它会自动调用迭代器的next() 方法。其实其更像 shell 语句中的 foreach
for 用于迭代器类型
迭代对象有一个 next() 方法,每次调用之后返回下一个条目,所有条目迭代完之后,迭代器引发 StopIteration 异常,终止循环,for 语句在内部调用 next() 并捕获异常。
range()
range(start,end,step = 1),返回一个列表。每个列表元素 k 都满足,start <= k < end.
range(start = 0,end, step = 1) # 报错,range() 不可以用过两个参数调用
实际上,为了运行速度,python2.x 实现了一个 迭代器对象 xrange(),其只在 for 循环中有效,其不返回列表。在 python3.x 中,range() 替代了 xrange(),并删除了 xrange()这个函数。
与序列相关的内建函数
sorted(),reversed().enumerate(),zip(),其中 sorted() 和 zip() 返回一个序列,另外两个函数返回一个迭代器(就是一个具有 next() 方法的对象,具有触发循环终止的能力)
else 可以放到 while,for 之后
迭代器和 iter() 函数
-
迭代器如何迭代? 迭代器又一个 next() 方法的对象,而不是通过索引来计数。每次调用 next() 方法返回下一个元素。全部的条目迭代结束之后,会引发一个 StopIteration,表示迭代完成。
- 迭代器的限制
- 不能向前移动
- 不能复制一个迭代器,如果想要再次迭代同个对象,需要重新建一个迭代器对象
- 使用迭代器
>>> myTuple = (123, 'xyz', 45.67)
>>> i = iter(myTuple)
>>> i.next()
123
>>> i.next()
'xyz'
>>> i.next()
45.67
>>> i.next()
Traceback (most recent call last):
File "", line 1, in ?
StopIteration
for i in seq:
do_something_to(i)
# 实际上是这样工作的:
fetch = iter(seq)
while True:
try:
i = fetch.next()
except StopIteration:
可变对象和迭代器
在迭代可变对象时,修改迭代对象时不可取的。而迭代器就能够避免这种问题,一个序列的迭代器只记录当前到达的元素,如果在迭代时改变了元素,会报错。
创建迭代器
iter(obj): obj 是一个序列
iter(func,sentinel),用类来创建迭代器,重复调用func,直到迭代器下一个值为 sentinel
列表解析
[expr for iter_var in iterable],其中 expr 是一个表达式
[expr for iter_var in iterable if cond_expr ],带 if 语句的 for 循环
生成器表达式
(expr for iter_var in iterable if cond_expr)
它与列表解析非常相似,而且它们的基本语法基本相同;不过它并不真正创建数字列表,而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目“产生”(yield)出来.生成器表达式使用了”延迟计算”(lazy evaluation)
用到的时候,才会生成,举一个例子
>>> s = [1,2,3]
>>> t = [4,5,6]
>>> x = ((i,j) for i in s for j in t)
>>> for item in x:
... print(item)
...
(1, 4)
(1, 5)
(1, 6)
(2, 4)
(2, 5)
(2, 6)
(3, 4)
(3, 5)
(3, 6)
生成器没有全部元素,只是每次计算下一个结果
第九章 文件和输入输出
工厂函数file()
该函数和 open()效果相同,在想说明处理文件对象的时候使用 file(),让程序的语意更清楚明白
通用换行符支持(UNS)
不同平台来表示行结束的符号是不同的,例如 \n,\r,或者 \r\n.当使用 rU 方式打开文件的时候,python 会将所有的行分隔符替换成 NEWLINE(\n)。这样按行读取的时候,兼容各种换行符。
处理行结束符
使用read() 或 readlines() 时,Python 不会删除行结束符,如果不做任何操作,字符串中多一个换行符,像这样:
One day
Two day
推荐使用strip()方法去除首尾的空格和换行符(参数为空,默认去除空格和换行符,不为空时,去除首尾的参数,如 strip(‘0’),去除首尾的 ‘0’)
f = open('myFile','r')
data = (line.strip() for line in f.readlines())
for line in data:
print(line) # 行和行之间不会多一个换行符
f.close()
文件内移动
seek() 和 C 语言中的 fseek()类似,有两个参数 offset(偏移量) 和 whence(从哪里开始,0 从文件开头,1 从当前位置,2 从结尾)
文件迭代
因为新版本 python 中的 file 对象集成了 next() 方法,因此在按行输出的时候,可以直接这样写
for line in f: # 而不必像以前的版本那样, for line in f.readlines(),二者效果相同
print(line.strip())
文件对象的垃圾回收机制
Python 垃圾收集机制也会在文件对象的引用计数将为 0 的时候,自动关闭文件。建议在用这个文件来赋值另一个文件对象之前关闭这个文件,如果不显式地关闭文件,很可能丢失输出缓存区的数据。
可以使用 flush() 方法,直接将内部缓冲区中的数据立刻写入到文件中。
文件方法杂项
print 方法默认给输出字符串的末尾添加了 ‘\n’,如果想不输出这个换行符,可以
print(s,) # 在参数最后添加一个 ,
不同平台的行分隔符不同,python 只要导入了 os 模块,以下这些变量都会被正确赋值
linesep 用于在文件中分隔行的字符串
sep 用来分隔文件路径名的字符串
pathsep 用于分隔文件路径的字符串
curdir 当前工作目录的字符串名称
pardir (当前工作目录的)父目录字符串名称
truncate([size]) 截断文件
默认从当前截断,输入 size 之后,将文件的前 size 部分截断,即删除 size 之后的部分
标准文件
通过 sys模块 来访问三个标准文件 sys.stdin(标准输入,一般是键盘),sys.stdout(标准输出,一般为到显示器的缓冲输出) 和 sys.stderr(标准错误,到屏幕的非缓冲输出),print 语句通常输出到 sys.stdout,raw_input() 通常输入到 sys.stdin。
??需要自己处理好换行符。。。
从 shell 中接收参数
sys.argv,接收参数数组,python 中不设置 sys.argc (即参数个数)
文件系统
有时候会使用 python 来管理一下文件,这时候会用到 os 这个模块的函数。
- remove()/unlink 删除文件
- rename() 重命名
- walk() 找到目录树下的所有文件名,相当于递归遍历
- chdir() 改变工作目录
- listdir() 列出指定目录下的文件
- getcwd() 返回当前工作目录
- mkdir()/mkdirs() 创建目录/创建多层目录
- rmdir() / removedirs() 删除目录/删除多层目录,只对空目录有效,当目录不为空时,采用 shutil.rmtree()来删除,或者配合 walk() 来删除,效果相同。
os.path 模块中的路径访问函数
- basename() 去掉目录路径,返回文件名,做爬虫时,用过
- dirname() 去掉文件名,返回目录路径
- join() 将分离的各部分组合成一个路径名
- split() 返回(dirname(),basename())元组
- splitdrive() 返回(dirvename,pathname) 元组,就是目录名和文件名
- getsize() 返回文件的大小
- exists() 指定路径是否存在
- isabs() 路径是否为绝对路径
- isdir() 指定路劲是否为目录
- isfile 指定路径是否为文件
- islink() 是否为符号链接
- samefile() 是否指向同一个文件
永久存储
python 真是服务周到,当编程者想保留一些信息的时候,又不想使用关系数据库管理系统,python 提供了在这种情景下使用的简单的永久性存储模块。当然,python 内置了不需要一个单独的服务器进程或操作的系统,并且不需要配置的关系数据库 SQLite, 某些情况可以考虑使用 SQLite。
- pickle 和 marshal 模块
pickle 模块依托文本文件,使用二进制写入和读出方式保存的对象。下面是小例子:
>>> import pickle
>>> class Person:
... def __init__(self,n,a):
... self.name = n
... self.age = a
... def show(self):
... print(self.name,str(self.age))
...
>>> p1 = Person('bob',2)
>>> p1.show()
bob 2
>>> f = open('p.txt','wb') # 使用二进制写入方式
>>> pickle.dump(p1,f,0) # 将对象写入
>>> f.close()
>>> f = open('p.txt','rb') # 使用二进制方式读
>>> bb = pickle.load(f) # 装载对象
>>> bb.show() # 执行对象的 show()
bob 2
>>> f.close()
marshal 用法和 pickle 类似
第十章 错误和异常
检测异常
try-except 语句和 try-finally 语句,或者是二者的复合语句,举个列子
>>> try:
... f = open('ball','r')
... except IOError as e: # 2.X版本支持 except IOError ,e: 这种写法,但是 3.X 不支持
... print(e)
...
[Errno 2] No such file or directory: 'ball'
同时处理多个异常
try:
client_obj.get_url(url)
except (URLError, ValueError, SocketTimeout):
client_obj.remove_url(url)
异常存在层级关系
可以用基类来捕获所有异常,如
try:
f = open(filename)
except (FileNotFoundError, PermissionError):
pass
可以被重写为
try:
f = open(filename)
except OSError:
pass
因为 OSError 是 FileNotFoundError 和 PermissionError 异常的基类
捕获多个异常捕获
try:
f = open('hh', 'r')
except (FileNotFoundError, ValueError) as e: # 只捕获其中的一个异常就会执行下面的操作,所以二者只用一个 as e 就行了
print(e)
可以基于状态码来做处理
用更一般的异常类型的状态码来做更详细的区分
import errno
filename = 'hh'
try:
f = open(filename)
except OSError as e:
if e.errno == errno.ENOENT:
print('File not found')
elif e.errno == errno.EACCES:
print('Permission denied')
else:
print('Unexpected error: %d', e.errno)
特别的异常优先
当匹配多个异常时,尽量让更一般的错误在最后,如果更一般的异常包含了特殊性的异常,更一般的异常会首先匹配,这样后面的特殊性的异常就不会被匹配了。比如这样
>>> try:
... f = open('missing')
... except OSError:
... print('It failed')
... except FileNotFoundError: # 不会被匹配,因为 OSError 包含了 FileNotFoundError
... print('File not found')
所有异常的基类 Exception 捕获所有的异常
自定义异常
创建自定义异常,让类来继承 Exception ,并书写判断条件,使用 raise 手动触发异常
class RunError(Exception):
def __init__(self, message, status):
super().__init__(message, status)
self.message = message
self.status = status
try:
i = 0
while True:
i += 1
if i > 100:
raise RunError(u'i 超过了 100', 0) # 使用 raise 来触发自定义异常
except RunError as e:
print(e.args) # 输出 ('i 超过了 100', 0) 异常将参数添加到 e.args 中
??是否可以自动触发自定义异常
python 没有往上层抛出异常
else 子句
没有检测到异常的时候,会运行 else 子句
finally 子句
无论异常是否发生,都会执行这段代码
with 语句
Python 对一些内建对象进行改进,加入了对上下文管理器的支持,可以用于 with 语句中,比如可以自动关闭文件、线程锁的自动获取和释放等。
with open(r'somefileName') as somefile:
for line in somefile:
print line
# ...more code
上面这段代码相当于用下面的 try/finally 方式实现,with 只是实现了 finally 语句,没有捕获异常,如果有异常,运行时依旧会抛出。
somefile = open(r'somefileName')
try:
for line in somefile:
print line
# ...more code
finally:
somefile.close()
已经加入对上下文管理协议支持的还有模块 threading、decimal 等
文管理器要实现上下文管理协议所需要的 enter() 和 exit() 两个方法: 自定义上下文管理器
assert 断言
assert 需要用 AssertionError 来捕获
try:
assert 1==0
except AssertionError:
print('不相等')
logging
日志
import logging
logging.basicConfig(level=logging.INFO) # 可以配置日志等级,有DEBUG,INFO,WARNING,ERROR 等级别
logging.info('n = %d' % n)
pdb 调试器
pdb 调试器类似于 gdb 调试器
第十一章 函数和函数式编程
关键字参数
foo(x = 42, y = 54)
这样的规范,允许参数缺失或者不按顺序,解释器通过给出的关键字来匹配参数的值
参数数组
可以将一个元组或者字典作为参数数组传递给函数。
func(*tuple_grp_nonkw_args, **dict_grp_kw_args) # 元组是一个 '*',字典是两个 '*'
前向引用
pyhton 不允许在函数声明之前,对其进行调用
函数属性
函数可以具有属性
匿名函数与 lambda
def Add2(x, y = 2):
return x + y
# 等价于下面
Add2 = lambda x, y=2:x + y
回调函数的内置函数
- reduce(函数名(参数1,参数2),可迭代对象)
reduce() 函数会将数据集合中的所有数据进行累积,运行过程为,先将数据集合中前两个元素去除,放进函数,得到结果,将结果和第三个元素作为参数,调用函数,如此,依次调用,返回最终的结果
from functools import reduce
def add(x,y):
return x + y
reduce(add,[1,2,3,4,5]) # 计算列表和
在 python3 中,reduce()函数已经从全局名字空间里移除了,现在被放置在 functools 中.
- map(函数名,可迭代对象)
第一个参数 function 以参数序列中的每个元素调用 function 函数,返回每次 function 函数返回值组成的新列表。其中 function 函数只有一个参数
>>> def square(x):
... return x**2
...
>>> map(square,[1,2,3,4])
<map object at 0x00000219B58BB080> # python3 返回的是一个迭代器
>>> s = map
>>> s = map(square,[1,2,3,4])
>>> for i in s:
... print(i)
...
1
4
9
16
>>>
- filter(函数名,可迭代对象)
来过滤数据集合中的元素
主要就是回调函数