0. 序言
- python 是一门脚本语言:封装性强,语法简洁,开发效率高,只用函数open就可以打开一个txt文件,只需要遍历就能读取这个txt文件。因为以上原因,python也广泛用于爬虫、数据处理和大数据以及人工智能,现在是大数据时代,所以python很火。如果是计算机研究生毕业,可以考虑人工智能,因为人工智能的岗位在学历方面卡的比较严,需要对算法数据结构等理论知识非常熟悉。
- python是一门解释性语言,代码执行效率没有java和c++高,但是取决于效率的主要是io和数据库的crud,所以python在以上场景下表现依然很优秀。因为就算你是法拉利,在北京二环上,你的速度等同于天津大发面包车。
- 学习python,以个人经历来看,不用购买python基础方面的书籍,慕课网的python入门和进阶两门课可以让你熟练掌握大部分python语法。不过在学习python之前,你最好问问自己Android进阶之光这本书涉及的板块以及binder原理是否都弄清楚了,如果说ok,那建议周末打游戏的时间学python,如果说no,那建议好好研究Android,毕竟去面试的岗位叫Android开发工程师,问的基本是java基础和android理论。当然工作需要例外。
- 因为工作需要,学习了下python基础知识,于是有了这篇博客!这篇博客主要总结了以下几个方面的知识,这些知识不得不牢牢掌握:
① 安装Python环境
② 变量和数据类型:Python内置的基本类型
③ List和Tuple:顺序的集合类型
④ 条件判断和循环:控制程序流程
⑤ Dict和Set:根据key访问的集合类型
⑥ 函数:定义和调用函数
⑦ 切片:如何对list进行切片
⑧ 迭代:如何用for循环迭代集合类型
⑨ 列表生成式:如何快速生成列表
1. Python之禅
- 人生苦短,我用Python.
2. 开发者
- 由荷兰人Guido van Rossum于1989年为了打发圣诞节的无聊而开发。
3. 特点
- 优雅
- 明确
- 简洁
4. 适用领域
- Web网站和各种网络服务
- 系统工具和脚本
- 作为“胶水”语言把其他语言开发的模块包装起来方便使用
5. 不适用的领域
- 贴近硬件的开发:比如 驱动程序 ----首选C
- 移动领域的开发:比如 Android Ios -----Swift、Kotlin
- 游戏开发:C/C++
6. Python的应用
- Youtube
- 豆瓣
- 闪电邮箱
- openstack 开源云计算平台
7. 与其他语言的对比的缺点
- C: 编译为机器码 运行速度非常快 代码量非常多
- Java:编译为字节码 运行速度快 代码量多
- Python缺点
①:解释执行 运行速度慢 代码量少(开发速度快);但是:我们并不需要运行速度那么快,速度瓶颈还是取决于网络调用和数据库操作,就好比F1在北京的三环高速公路上,堵车你也开不了那么快。
②:Python源码不能够加密:所以通过Python提供服务赚钱。
8. 安装
- Python跨平台:Window开发的,可以运行在Mac、Linux等系统上。
- 很多库暂时不兼容3.3,所以暂时安装Python 2.7
- 官网:https://www.python.org/
- 步骤:Downloads_Window_2.7.14
- 下载完成_一直Next即可。
9. 安装环境
- E:\Python 添加到Path中即可
- 命令行输入 python 显示版本号 证明安装正确
- 建议使用cmder这款命令行工具
10. 第一个Python程序-Hello World (初恋的感觉)
- 命令行:打开命令行工具cmder,输入第一个Python程序
>>> print 'Hello,World!'
Hello,World!
- NotePad:
① 设置:首选项-新建-windows-utf-8 ② 语言:python
print 'Hello,World!' 记得一定要定格左边写 保存为扩展名为py的文件
② 打印: 进入到文件所在盘符,打开命令行,然后输入python helloworld.py:
D:\>python helloworld.py
Hello,World!
11. 数据类型
- 整数:
- 整数的书写和数学一样,而且有负整数,如 0,-80
- 机器采用二进制,我们使用十六进制(0x开头,由0-9,a-f组成)表示整数更好,如 0x10,0xaf10
- 浮点数:
- 浮点数就是小号:比如1.23,2.31,而对于很大或者很小的浮点数,就必须用科学计数法表示:把10用e替代,比如1.23x10^9就是1.23e9,再比如0.000012可以写成1.2e-5。
- 注意:整数和浮点数在计算机中的存储方式是不同的,整数的运算永远是精确的(除法也是精确的),而浮点数在运算中会有误差。
-
字符串:字符串可以用单引号或者多引号包裹起来表示:"abc",'abc'
-
布尔值:
- 布尔值指的是True或者False,非0就是Ture,0就是False
- 布尔值的运算可以通过运算符来进行:and(有false则false),or(有true则true),not(把true变为false或者false变为true)
-
空值:空值用none表示,none不表示为0,0是有意义的,None是一个特殊的空值。
-
练习:
试一试,在右边编辑器中,完成以下任务:
- 计算十进制整数 45678 和十六进制整数 0x12fd2 之和。
- 请用字符串表示出Learn Python in imooc。
- 请计算以下表达式的布尔值(注意==表示判断是否相等):
100 < 99
0xff == 255
注意:使用print命令
print 45678+0x12fd2
print "Learn Python in imooc"
print 100<99
123456
Learn Python in imooc
False
12. print语句
- 多个字符串可以用“,”逗号来进行连接,然后直接一起输出:
(print 会依次打印每个字符串,遇到逗号就插入一个空格)
print 'hello','world','you','and','me'
hello world you and me
- 可以打印整数
print 300+500
800
- 注意(字符串、逗号、数学计算):
print '100+200=',100+200
100+200= 300
13. 注释
print 'hello,world' # 这是我的第一个Python程序
File "index.py", line 1
SyntaxError: Non-ASCII character '\xe8' in file index.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
- 这是缺乏编码方式导致的,所以在文件头部添加:
# coding=utf-8
- 完整代码:
# coding=utf-8
print 'hello,world' # 这是我的第一个Python程序
- 注释代码:
# print 'hello,world'
14. 变量
- 变量名:大小写英文或者英文加数字或者英文加数字加下划线的组合:
x1 = 1
d = 3
x100 = x1+d
_d100 = x100
s = _d100
print s
a = 1 # a是一个整数
t_007 = 'T007' t_007是一个字符串
- 等号=是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量:
a = 123 # a是整数
print a
a = 'imooc' # a变为字符串
print a
这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。
- 当我们写:a = 'ABC'时,Python解释器干了两件事情:
- 在内存中创建了一个'ABC'的字符串;
- 在内存中创建了一个名为a的变量,并把它指向'ABC'。
15. 小测验
- 等差数列可以定义为每一项与它的前一项的差等于一个常数,可以用变量 x1 表示等差数列的第一项,用 d 表示公差,请计算数列
1 4 7 10 13 16 19 ...
前 100 项的和。
a = 1
x1 = 3
a_100 = 1+x1*99
print (a_100+a)*50
14950
16. 定义字符串
- 如果字符串本身包含'怎么办?比如我们要表示字符串 I'm OK ,这时,可以用" "括起来表示:
"I'm OK"
- 如果字符串包含",我们就可以用' '括起来表示:
'Learn "Python" in imooc'
- 如果字符串既包含'又包含",这个时候,就需要对字符串的某些特殊字符进行“转义”,Python字符串用\进行转义,比如要表示字符串 Bob said "I'm OK".
由于 ' 和 " 会引起歧义,因此,我们在它前面插入一个\表示这是一个普通字符,不代表字符串的起始
'Bob said \"I\'m OK\".'
- 常用的转义字符:
\n 表示换行
\t 表示一个制表符
\\ 表示 \ 字符本身
17. raw字符串与多行字符串
- raw:
r'\(~_~)/ \(~_~)/'
- 多行:
'''Line 1
Line 2
Line 3'''
- 注意:r'...'表示法不能表示多行字符串,也不能表示包含'和 "的字符串,但是r''' '''可以:
print r'''"To be, or not to be": that is the question.
Whether it's nobler in the mind to suffer.'''
18. Unicode字符串
-
计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最多个数是(二进制11111111=十进制255),0 - 127被用来表示大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母 A 的编码是65,小写字母 z 的编码是122。
-
如果要表示中文,显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。
-
类似的,日文和韩文等其他语言也有这个问题。为了统一所有文字的编码,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。
-
Unicode通常用两个字节表示一个字符,原有的英文编码从单字节变成双字节,只需要把高字节全部填为0就可以
-
为Python的诞生比Unicode标准发布的时间还要早,所以最早的Python只支持ASCII编码,普通的字符串'ABC'在Python内部都是ASCII编码的。
-
Python在后来添加了对Unicode的支持,以Unicode表示的字符串用u'...'表示。
-
Python在后来添加了对Unicode的支持,以Unicode表示的字符串用u'...'表示,比如:
print u'中文'
中文
- Unicode字符串除了多了一个 u 之外,与普通字符串没啥区别,转义字符和多行表示法仍然有效:
u'中文\n日文\n韩文'
u'''第一行
第二行'''
ur'''Python的Unicode字符串支持"中文",
"日文",
"韩文"等多种语言'''
- 如果中文字符串在Python环境下遇到 UnicodeDecodeError,这是因为.py文件保存的格式有问题。可以在第一行添加注释,目的是告诉Python解释器,用UTF-8编码读取源代码
# -*- coding: utf-8 -*-
19. 整数和浮点数
- 整数和浮点数直接进行运算
1 + 2 + 3 # ==> 6
4 * 5 - 6 # ==> 14
7.5 / 8 + 2.1 # ==> 3.0375
- 使用括号可以提升优先级
(1 + 2) * 3 # ==> 9
(2.2 + 3.3) / (1.5 * (9 - 0.3)) # ==> 0.42145593869731807
- 和数学运算不同的地方是,Python的整数运算结果仍然是整数,浮点数运算结果仍然是浮点数:
1 + 2 # ==> 整数 3
1.0 + 2.0 # ==> 浮点数 3.0
- 整数和浮点数混合运算的结果就变成浮点数了
1 + 2.0 # ==> 浮点数 3.0
- Python的整数除法,即使除不尽,结果仍然是整数,余数直接被扔掉。不过,Python提供了一个求余的运算 % 可以计算余数:
11 % 4 # ==> 3
- 如果我们要计算 11 / 4 的精确结果,按照“整数和浮点数混合运算的结果是浮点数”的法则,把两个数中的一个变成浮点数再运算就没问题了:
11.0 / 4 # ==> 2.75
20.布尔类型
- 与运算:有false则false。
True and True # ==> True
True and False # ==> False
False and True # ==> False
False and False # ==> False
- 或运算:有true则true。
True or True # ==> True
True or False # ==> True
False or True # ==> True
False or False # ==> False
- 非运算:把True变为False,或者把False变为True:
not True # ==> False
not False # ==> True
- 布尔类型还可以与其他数据类型做 and、or和not运算
a = True
print a and 'a=T' or 'a=F'
-
Python把0、空字符串''和None看成 False,其他数值和非空字符串都看成 True。
-
and 和 or 运算的一条重要法则:短路计算。计算 a and b 时,如果 a 是 False,则根据与运算法则,整个结果必定为 False,因此返回 a;如果 a 是 True,则整个计算结果必定取决与 b,因此返回 b。
-
计算 a or b 时,如果 a 是 True,则根据或运算法则,整个计算结果必定为 True,因此返回 a;如果 a 是 False,则整个计算结果必定取决于 b,因此返回 b。
21. 创建list
- list是一种有序的集合,可以随时添加和删除其中的元素:
>>> ['Michael', 'Bob', 'Tracy']
['Michael', 'Bob', 'Tracy']
- 直接用 [ ] 把list的所有元素都括起来,就是一个list对象。通常,我们会把list赋值给一个变量,这样,就可以通过变量来引用list:
>>> classmates = ['Michael', 'Bob', 'Tracy']
>>> classmates # 打印classmates变量的内容
['Michael', 'Bob', 'Tracy']
- Python是动态语言,所以list中包含的元素并不要求都必须是同一种数据类型,我们完全可以在list中包含各种数据:
>>> L = ['Michael', 100, True]
- 一个元素也没有的list,就是空list:
>>> empty_list = []
22. 按照索引访问list
- 要打印第一名同学的名字,用 L[0]:
>>> L = ['Adam', 'Lisa', 'Bart']
>>> print L[0]
Adam
23. 倒序访问list:
>>> L = ['Adam', 'Lisa', 'Bart']
>>> print L[-1]
Bart
24. list添加新元素:
- append() 方法(总是把新的元素添加到 list 的尾部):
>>> L = ['Adam', 'Lisa', 'Bart']
>>> L.append('Paul')
>>> print L
['Adam', 'Lisa', 'Bart', 'Paul']
- insert()方法,它接受两个参数,第一个参数是索引号,第二个参数是待添加的新元素:
>>> L = ['Adam', 'Lisa', 'Bart']
>>> L.insert(0, 'Paul')
>>> print L
['Paul', 'Adam', 'Lisa', 'Bart']
25. list删除元素
- pop():
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> L.pop()
'Paul'
>>> print L
['Adam', 'Lisa', 'Bart']
pop()方法总是删掉list的最后一个元素,并且它还返回这个元素,所以我们执行 L.pop() 后,会打印出 'Paul'
- pop(2):
>>> L.pop(2)
'Paul'
>>> print L
['Adam', 'Lisa', 'Bart']
- 小练习:
L = ['Adam', 'Lisa', 'Paul', 'Bart']
Paul的索引是2,Bart的索引是3,如果我们要把Paul和Bart都删掉
L = ['Adam', 'Lisa', 'Paul', 'Bart']
L.pop(2)
L.pop(2)
print L
26. 替换元素
- 对list中的某一个索引赋值,就可以直接用新的元素替换掉原来的元素,list包含的元素个数保持不变
>>> L = ['Adam', 'Lisa', 'Bart']
>>> L[2] = 'Paul'
>>> print L
L = ['Adam', 'Lisa', 'Paul']
27. 创建tuple
- tuple是另一种有序的列表,中文翻译为“ 元组 ”。tuple 和 list 非常类似,但是,tuple一旦创建完毕,就不能修改了。
>>> t = ('Adam', 'Lisa', 'Bart')
创建tuple和创建list唯一不同之处是用( )替代了[ ]
获取 tuple 元素的方式和 list 是一模一样的,我们可以正常使用 t[0],t[-1]等索引方式访问元素
28. 创建单元素tuple
- 包含 0 个元素的 tuple,也就是空tuple,直接用 ()表示
>>> t = ()
>>> print t
()
- 创建包含1个元素的 tuple
>>> t = (1,)
>>> print t
(1,)
因为用()定义单元素的tuple有歧义,所以 Python 规定,单元素 tuple 要多加一个逗号“,”
29. “可变”的tuple
>>> t = ('a', 'b', ['A', 'B'])
>>> L = t[2]
>>> L[0] = 'X'
>>> L[1] = 'Y'
>>> print t
('a', 'b', ['X', 'Y'])
-
注意:tuple的元素确实变了,但其实变的不是 tuple 的元素,而是list的元素。
-
tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向'a',就不能改成指向'b',指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!
-
理解了“指向不变”后,要创建一个内容也不变的tuple怎么做?那就必须保证tuple的每一个元素本身也不能变。
-
小练习:定义了tuple:
t = ('a', 'b', ['A', 'B'])
由于 t 包含一个list元素,导致tuple的内容是可变的。能否修改上述代码,让tuple内容不可变?
t = ('a', 'b', ('A', 'B'))
print t
29. if语句
age = 20
if age >= 18:
print 'your age is', age
print 'adult'
print 'END'
-
注意: Python代码的缩进规则。具有相同缩进的代码被视为代码块,上面的3,4行 print 语句就构成一个代码块(但不包括第5行的print)。如果 if 语句判断为 True,就会执行这个代码块。
-
缩进请严格按照Python的习惯写法:4个空格,不要使用Tab,更不要混合Tab和空格,否则很容易造成因为缩进引起的语法错误。
-
注意: if 语句后接表达式,然后用:表示代码块开始。
-
如果你在Python交互环境下敲代码,还要特别留意缩进,并且退出缩进需要多敲一行回车:
>>> age = 20
>>> if age >= 18:
... print 'your age is', age
... print 'adult'
...
your age is 20
adult
30. if-else
if age >= 18:
print 'adult'
else:
print 'teenager'
- 注意: else 后面有个“:”
31. if-elif-else
条件1:18岁或以上:adult
条件2:6岁或以上:teenager
条件3:6岁以下:kid
if age >= 18:
print 'adult'
elif age >= 6:
print 'teenager'
elif age >= 3:
print 'kid'
else:
print 'baby'
- 特别注意: 这一系列条件判断会从上到下依次判断,如果某个判断为 True,执行完对应的代码块,后面的条件判断就直接忽略,不再执行了。
32. for
L = ['Adam', 'Lisa', 'Bart']
for name in L:
print name
-
注意: name 这个变量是在 for 循环中定义的,意思是,依次取出list中的每一个元素,并把元素赋值给 name,然后执行for循环体(就是缩进的代码块)。
-
小练习:班里考试后,老师要统计平均成绩,已知4位同学的成绩用list表示如下:
L = [75, 92, 59, 68]
请利用for循环计算出平均成绩。
L = [75, 92, 59, 68]
sum = 0.0
for score in L:
sum = sum + score
print sum / 4
33. while循环
- while 循环不会迭代 list 或 tuple 的元素,而是根据表达式判断循环是否结束:比如要从 0 开始打印不大于 N 的整数:
N = 10
x = 0
while x < N:
print x
x = x + 1
- 小练习:利用while循环计算100以内奇数的和
sum = 0
x = 1
while x < 100:
sum = sum + x
x = x + 2
print sum
34. break退出循环
- 比如计算1至100的整数和,我们用while来实现
sum = 0
x = 1
while True:
sum = sum + x
x = x + 1
if x > 100:
break
print sum
- 小练习:利用 while True 无限循环配合 break 语句,计算 1 + 2 + 4 + 8 + 16 + ... 的前20项的和:
sum = 0
x = 1
n = 1
while True:
sum = sum + x
x = 2*x
n = n+1
if n > 20:
break
print sum
35. continue继续循环
-
continue跳过后续循环代码,继续下一次循环:
现在老师只想统计及格分数的平均分,就要把 x < 60 的分数剔除掉,这时,利用 continue,可以做到当 x < 60的时候,不继续执行循环体的后续代码,直接进入下一次循环:
L = [75, 98, 59, 81, 66, 43, 69, 85]
sum = 0.0
n = 0
for x in L:
sum = sum + x
n = n + 1
print sum / n
for x in L:
if x < 60:
continue
sum = sum + x
n = n + 1
-
小练习:
对已有的计算 0 - 100 的while循环进行改造,通过增加 continue 语句,使得只计算奇数的和
sum = 0
x = 1
while True:
sum = sum + x
x = x + 1
if x > 100:
break
print sum
sum = 0
x = 0
while True:
x = x + 1
if x > 100:
break
if x % 2 == 0:
continue
sum = sum + x
print sum
36. 多重循环
- 在循环内部,还可以嵌套循环
for x in ['A', 'B', 'C']:
for y in ['1', '2', '3']:
print x + y
A1
A2
A3
B1
B2
B3
C1
C2
C3
- 小练习:对100以内的两位数,请使用一个两重循环打印出所有十位数数字比个位数数字小的数,例如,23(2 < 3)
for x in [1,2,3,4,5,6,7,8,9 ]:
for y in [ 0,1,2,3,4,5,6,7,8,9 ]:
if x < y :
print x*10+y
37. dict
- 给定一个名字,就可以直接查到分数,这就是dict的作用,名字称为key,对应的成绩称为value,dict就是通过 key 来查找 value
- 花括号 {} 表示这是一个dict,然后按照 key: value, 写出来即可。最后一个 key: value 的逗号可以省略。
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
- len() 函数可以计算任意集合的大小:
>>> len(d)
3
38. 访问dict
- 可以简单地使用 d[key] 的形式来查找对应的 value,这和 list 很像,不同之处是,list 必须使用索引返回对应的元素,而dict使用key
>>> print d['Adam']
95
>>> print d['Paul']
Traceback (most recent call last):
File "index.py", line 11, in <module>
print d['Paul']
KeyError: 'Paul'
- 通过 key 访问 dict 的value,只要 key 存在,dict就返回对应的value。如果key不存在,会直接报错:KeyError,要避免 KeyError 发生,有两个办法:
- 先判断一下 key 是否存在,用 in 操作符:
if 'Paul' in d:
print d['Paul']
- 使用dict本身提供的一个 get 方法,在Key不存在的时候,返回None:
>>> print d.get('Bart')
59
>>> print d.get('Paul')
None
- 小练习:根据如下dict,请打印出:
Adam: 95
Lisa: 85
Bart: 59
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
print 'Adam:',d.get('Adam')
print 'Lisa:',d.get('Lisa')
print 'Bart:',d.get('Bart')
39. dict的特点
-
dict的第一个特点是查找速度快,无论dict有10个元素还是10万个元素,查找速度都一样。而list的查找速度随着元素增加而逐渐下降。
不过dict的查找速度快不是没有代价的,dict的缺点是占用内存大,还会浪费很多内容,list正好相反,占用内存小,但是查找速度慢。
-
dict的第二个特点就是存储的key-value序对是没有顺序的!这和list不一样:
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
>>> print d
{'Lisa': 85, 'Adam': 95, 'Bart': 59}
- dict的第三个特点是作为 key 的元素必须不可变,Python的基本类型如字符串、整数、浮点数都是不可变的,都可以作为 key。但是list是可变的,就不能作为 key;最常用的key还是字符串,因为用起来最方便
{
'123': [1, 2, 3], # key 是 str,value是list
123: '123', # key 是 int,value 是 str
('a', 'b'): True # key 是 tuple,并且tuple的每个元素都是不可变对象,value是 boolean
}
40. 更新dict
- 随时往dict中添加新的 key-value。比如已有dict:要把新同学'Paul'的成绩 72 加进去,用赋值语句:
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
>>> d['Paul'] = 72
>>> print d
{'Lisa': 85, 'Paul': 72, 'Adam': 95, 'Bart': 59}
- 如果 key 已经存在,则赋值会用新的 value 替换掉原来的 value:
>>> d['Bart'] = 60
>>> print d
{'Lisa': 85, 'Paul': 72, 'Adam': 95, 'Bart': 60}
41. 遍历dict
- 直接使用for循环可以遍历 dict 的 key,由于通过 key 可以获取对应的 value,因此,在循环体内,可以获取到value的值:
>>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
>>> for key in d:
... print key
...
Lisa
Adam
Bart
- 小练习:请用 for 循环遍历如下的dict,打印出 name: score 来
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
for key in d:
print key,':',d.get(key)
42. set
- dict的作用是建立一组 key 和一组 value 的映射关系,dict的key是不能重复的
- 有的时候,我们只想要 dict 的 key,不关心 key 对应的 value,目的就是保证这个集合的元素不会重复,这时,set就派上用场了:
- set 持有一系列元素,这一点和 list 很像,但是set的元素没有重复,而且是无序的,这点和 dict 的 key很像
- 创建 set 的方式是调用 set() 并传入一个 list,list的元素将作为set的元素:
>>> s = set(['A', 'B', 'C'])
>>> print s
set(['A', 'C', 'B'])
上述打印的形式类似 list, 但它不是 list,仔细看还可以发现,打印的顺序和原始 list 的顺序有可能是不同的,因为set内部存储的元素是无序的
- set不能包含重复的元素,所以,当我们传入包含重复元素的 list,set会自动去掉重复的元素,原来的list有4个元素,但set只有3个元素
>>> s = set(['A', 'B', 'C', 'C'])
>>> print s
set(['A', 'C', 'B'])
>>> len(s)
3
43. 访问set
- 由于set存储的是无序集合,所以我们没法通过索引来访问。
- 用 in 操作符判断:看来大小写很重要,'Bart' 和 'bart'被认为是两个不同的元素:
>>> 'Bart' in s
True
>>> 'bart' in s
False
44. set的特点
- set的内部结构和dict很像,唯一区别是不存储value,,因此,判断一个元素是否在set中速度很快。
- set存储的元素和dict的key类似,必须是不变对象,因此,任何可变对象是不能放入set中的.
- set存储的元素也是没有顺序的.
- 假设我们让用户输入星期一至星期日的某天,如何判断用户的输入是否是一个有效的星期呢?
# if 语句
x = '???' # 用户输入的字符串
if x!= 'MON' and x!= 'TUE' and x!= 'WED' ... and x!= 'SUN':
print 'input error'
else:
print 'input ok'
# set 集合
weekdays = set(['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'])
x = '???' # 用户输入的字符串
if x in weekdays:
print 'input ok'
else:
print 'input error'
45. 遍历set
- for 循环
>>> s = set(['Adam', 'Lisa', 'Bart'])
>>> for name in s:
... print name
...
Lisa
Adam
Bart
- 小练习:请用 for 循环遍历如下的set,打印出 name: score 来
s = set([('Adam', 95), ('Lisa', 85), ('Bart', 59)])
s = set([('Adam', 95), ('Lisa', 85), ('Bart', 59)])
for x in s:
print x[0]+":",x[1]
- 注意:注意到set的元素是tuple,因此 for 循环的变量被依次赋值为tuple
46. 更新set
- set存储的是一组不重复的无序元素,因此,更新set主要做两件事:一是把新的元素添加到set中,二是把已有元素从set中删除。
- 增加:set的add()方法:
>>> s = set([1, 2, 3])
>>> s.add(4)
>>> print s
set([1, 2, 3, 4])
- 删除:set的remove()方法:
>>> s = set([1, 2, 3, 4])
>>> s.remove(4)
>>> print s
set([1, 2, 3])
- Care:如果删除的元素不存在set中,remove()会报错:用add()可以直接添加,而remove()前需要判断:
>>> s = set([1, 2, 3])
>>> s.remove(4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 4
47. 函数
- Python不但能非常灵活地定义函数,而且本身内置了很多有用的函数,可以直接调用,说白了函数就是方法:对公共代码的封装。
48. 调用函数
- Python内置了很多有用的函数,我们可以直接调用。
- 求绝对值的函数 abs,它接收一个参数:
>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34
- 函数 cmp(x, y) 就需要两个参数,如果 x<y,返回 -1,如果 x==y,返回 0,如果 x>y,返回 1:
>>> cmp(1, 2)
-1
>>> cmp(2, 1)
1
>>> cmp(3, 3)
0
- 数据类型转换函数,比如 int()函数可以把其他数据类型转换为整数:
>>> int('123')
123
>>> int(12.34)
12
- str()函数把其他类型转换成 str:
>>> str(123)
'123'
>>> str(1.23)
'1.23'
- sum()函数接受一个list作为参数,并返回list所有元素之和:请计算 1 * 1 + 2 * 2 + 3 * 3 + ... + 100 * 100:
L = []
x = 1
while x <= 100 :
L.append(x*x)
x = x + 1
print sum(L)
49. 编写函数
- 定义一个函数要使用 def 语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回:
自定义一个求绝对值的 my_abs 函数:
def my_abs(x):
if x >= 0:
return x
else:
return -x
- 如果没有return语句,函数执行完毕后也会返回结果,只是结果为 None 。 return None可以简写为return。
- 小练习:请定义一个 square_of_sum 函数,它接受一个list,返回list中每个元素平方的和:
def square_of_sum(L):
sum = 0
for num in L :
sum = num*num +sum
return sum
print square_of_sum([1, 2, 3, 4, 5])
print square_of_sum([-5, 0, 5, 15, 25])
50. 函数之返回多值
-
math包提供了sin()和 cos()函数,我们先用import引用它
import math
def move(x, y, step, angle):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print x, y
151.961524227 70.0
- 其实这只是一种假象,Python函数返回的仍然是单一值:返回值是一个tuple!
>>> r = move(100, 100, 60, math.pi / 6)
>>> print r
(151.96152422706632, 70.0)
-
在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。
-
小练习:一元二次方程的定义是:ax² + bx + c = 0 请编写一个函数,返回一元二次方程的两个解。注意:Python的math包提供了sqrt()函数用于计算平方根。请参考求根公式:x = (-b±√(b²-4ac)) / 2a
import math
def quadratic_equation(a, b, c):
t = math.sqrt(b * b - 4 * a * c)
return (-b + t) / (2 * a),( -b - t )/ (2 * a)
print quadratic_equation(2, 3, 0)
print quadratic_equation(1, -6, 5)
51. 递归函数
- 在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数:
- 阶乘 n! = 1 * 2 * 3 * ... * n,用函数 fact(n)表示:fact(n)可以表示为 n * fact(n-1),只有n=1时需要特殊处理,于是,fact(n)用递归的方式写出来就是:
fact(n) = n! = 1 * 2 * 3 * ... * (n-1) * n = (n-1)! * n = fact(n-1) * n
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
-
Care: 使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试计算 fact(10000)
-
小练习:汉诺塔 (http://baike.baidu.com/view/191666.htm) 的移动也可以看做是递归函数:我们对柱子编号为a, b, c,将所有圆盘从a移到c可以描述为:
如果a只有一个圆盘,可以直接移动到c;
如果a有N个圆盘,可以看成a有1个圆盘(底盘) + (N-1)个圆盘,首先需要把 (N-1) 个圆盘移动到 b,然后,将 a的最后一个圆盘移动到c,再将b的(N-1)个圆盘移动到c。
请编写一个函数,给定输入 n, a, b, c,打印出移动的步骤:
move(n, a, b, c)
例如,输入 move(2, 'A', 'B', 'C'),打印出:
A --> B
A --> C
B --> C
# -*- coding: utf-8 -*
def move(n, a, b, c):
if n > 1:
move(n-1,a,c,b)
print a,'-->',c
move(n-1,b,a,c)
else :
print a,'-->',c
move(4, 'A', 'B', 'C')
52. 定义默认参数
- int() 函数,其实就有两个参数,我们既可以传一个参数,又可以传两个参数:
>>> int('123')
123
>>> int('123', 8)
83
- int()函数的第二个参数是转换进制,如果不传,默认是十进制 (base=10),如果传了,就用传入的参数
- 函数的默认参数的作用是简化调用,你只需要把必须的参数传进去。
- 但是在需要的时候,又可以传入额外的参数来覆盖默认参数值。
# x 的 N次方
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
# 把 n 的默认值设定为 2
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
>>> power(5)
25
- Care:由于函数的参数按从左到右的顺序匹配,所以默认参数只能定义在必需参数的后面:
# OK:
def fn1(a, b=1, c=2):
pass
# Error:
def fn2(a=1, b):
pass
- 小练习:请定义一个 greet() 函数,它包含一个默认参数,如果没有传入,打印 'Hello, world.',如果传入,打印 'Hello, xxx.'
# 逗号如果作为连接符会生成一个空格;建议用+号连接
def greet(name = 'world'):
print 'Hello,'+name+'.'
greet()
greet('Bart')
53. 定义可变参数
- 可变参数的名字前面有个 * 号,我们可以传入0个、1个或多个参数给可变参数
def fn(*args):
print args
>>> fn()
()
>>> fn('a')
('a',)
>>> fn('a', 'b')
('a', 'b')
>>> fn('a', 'b', 'c')
('a', 'b', 'c')
- Python解释器会把传入的一组参数组装成一个tuple传递给可变参数,因此,在函数内部,直接把变量 args 看成一个 tuple 就好了
- 定义可变参数的目的也是为了简化调用:平均数:
>>> average()
0
>>> average(1, 2)
1.5
>>> average(1, 2, 2, 3, 4)
2.4
- 小练习:请编写接受可变参数的 average() 函数
# 可变参数 args 是一个tuple,当0个参数传入时,args是一个空tuple.
def average(*args):
sum = 0.0
if len(args) == 0 :
return sum
for x in args:
sum = sum + x
return sum/len(args)
print average()
print average(1, 2)
print average(1, 2, 2, 3, 4)
54. 对list进行切片
- 切片的意思就是从中取值生成一个新的list
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> L[0:3]
['Adam', 'Lisa', 'Bart']
# L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素
- 如果第一个索引是0,还可以省略:
>>> L[:3]
['Adam', 'Lisa', 'Bart']
- 也可以从索引1开始,取出2个元素出来:
>>> L[1:3]
['Lisa', 'Bart']
- 只用一个 : ,表示从头到尾:L[:]实际上复制出了一个新list
>>> L[:]
['Adam', 'Lisa', 'Bart', 'Paul']
- 切片操作还可以指定第三个参数,第三个参数表示每N个取一个,上面的 L[::2] 会每两个元素取出一个来,也就是隔一个取一个。
>>> L[::2]
['Adam', 'Bart']
- 把list换成tuple,切片操作完全相同,只是切片的结果也变成了tuple
- 小练习:range()函数可以创建一个数列:请利用切片,取出:1. 前10个数;2. 3的倍数;3. 不大于50的5的倍数。
>>> range(1, 101)
[1, 2, 3, ..., 100]
L = range(1, 101)
print L[0:10]
print L[2:100:3]
print L[4:50:5]
55. 倒序切片
- 记住倒数第一个元素的索引是-1。倒序切片包含起始索引,不包含结束索引
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> L[-2:]
['Bart', 'Paul']
>>> L[:-2]
['Adam', 'Lisa']
>>> L[-3:-1]
['Lisa', 'Bart']
>>> L[-4:-1:2]
['Adam', 'Bart']
- 小练习:利用倒序切片对 1 - 100 的数列取出:* 最后10个数;* 最后10个5的倍数。
L = range(1, 101)
print L[-10:]
print L[-46::5]
56. 字符串切片
- Python没有针对字符串的截取函数,只需要切片一个操作就可以完成,非常简单
>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[-3:]
'EFG'
>>> 'ABCDEFG'[::2]
'ACEG'
- 小练习:字符串有个方法 upper() 可以把字符变成大写字母:
>>> 'abc'.upper()
'ABC'
但它会把所有字母都变成大写。请设计一个函数,它接受一个字符串,然后返回一个仅首字母变成大写的字符串。提示:利用切片操作简化字符串操作。
def firstCharUpper(s):
return s[:1].upper()+s[1:]
print firstCharUpper('hello')
print firstCharUpper('sunday')
print firstCharUpper('september')
57. 迭代
- 迭代在Python中就是 for 循环。
- Python 的 for循环不仅可以用在list或tuple上,还可以作用在其他任何可迭代对象上。
- 迭代操作就是对于一个集合,无论该集合是有序还是无序,我们用 for 循环总是可以依次取出集合的每一个元素
- 集合是指包含一组元素的数据结构,我们已经介绍的包括:
- 有序集合:list,tuple,str和unicode;
- 无序集合:set
- 无序集合并且具有 key-value 对:dict
- 小练习:请用for循环迭代数列 1-100 并打印出7的倍数
L = []
x = 1
while x > 0 :
if x >100 :
break
L.append(x)
x = x +1
for i in L:
if i % 7==0:
print i
58. 索引迭代
- 迭代永远是取出元素本身,而非元素的索引.但是对于有序集合,元素确实是有索引的。有的时候,我们确实想在 for 循环中拿到索引, 这时候就要靠enumerate() 函数:
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> for index, name in enumerate(L):
... print index, '-', name
...
0 - Adam
1 - Lisa
2 - Bart
3 - Paul
- 实际上enumerate() 函数是把list中的每一个元素变成了tuple:
['Adam', 'Lisa', 'Bart', 'Paul']
[(0, 'Adam'), (1, 'Lisa'), (2, 'Bart'), (3, 'Paul')]
- 迭代的每一个元素实际上是一个tuple:
for t in enumerate(L):
index = t[0]
name = t[1]
print index, '-', name
- 简写为:
for index, name in enumerate(L):
print index, '-', name
- 索引迭代也不是真的按索引访问,而是由 enumerate() 函数自动把每个元素变成 (index, element) 这样的tuple,再迭代,就同时获得了索引和元素本身.
- 小练习:zip()函数可以把两个 list 变成一个 list:
>>> zip([10, 20, 30], ['A', 'B', 'C'])
[(10, 'A'), (20, 'B'), (30, 'C')]
- 小练习:zip()函数可以把两个 list 变成一个 list:
>>> zip([10, 20, 30], ['A', 'B', 'C'])
[(10, 'A'), (20, 'B'), (30, 'C')]
- 需求:在迭代 ['Adam', 'Lisa', 'Bart', 'Paul'] 时,如果我们想打印出名次 - 名字(名次从1开始),请考虑如何在迭代中打印出来。
提示:考虑使用zip()函数和range()函数:range(1, ?) 可以创建出起始为 1 的数列。
L = ['Adam', 'Lisa', 'Bart', 'Paul']
for index, name in zip(range(1, len(L)+1), L):
print index, '-', name
- 迭代dict的value
-
dict对象本身就是可迭代对象,用 for 循环直接迭代 dict,可以每次拿到dict的一个key,如果迭代value,可以使用values() 方法,这个方法把dict转换成一个包含所有value的list,这样,我们迭代的就是 dict的每一个 value。
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.values()
# [85, 95, 59]
for v in d.values():
print v
# 85
# 95
# 59
- dict除了values()方法外,还有一个 itervalues() 方法,用 itervalues() 方法替代 values() 方法,迭代效果完全一样
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.itervalues()
# <dictionary-valueiterator object at 0x106adbb50>
for v in d.itervalues():
print v
# 85
# 95
# 59
- 不同之处:
- values() 方法实际上把一个 dict 转换成了包含 value 的list。
- 但是 itervalues() 方法不会转换,它会在迭代过程中依次从 dict 中取出 value,所以 itervalues() 方法比 values() 方法节省了生成 list 所需的内存。
- 打印 itervalues() 发现它返回一个 <dictionary-valueiterator> 对象,这说明在Python中,for 循环可作用的迭代对象远不止 list,tuple,str,unicode,dict等,任何可迭代对象都可以作用于for循环,而内部如何迭代我们通常并不用关心。
- 小练习:给定一个dict:
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59, 'Paul': 74 }
请计算所有同学的平均分。
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59, 'Paul': 74 }
sum = 0.0
for x in d.itervalues():
sum = sum +x
print sum/len(d)
60. 迭代dict的key和value
- items() 方法:items() 方法把dict对象转换成了包含tuple的list,我们对这个list进行迭代,可以同时获得key和value:
>>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
>>> print d.items()
[('Lisa', 85), ('Adam', 95), ('Bart', 59)]
>>> for key, value in d.items():
... print key, ':', value
...
Lisa : 85
Adam : 95
Bart : 59
-
iteritems() 方法:iteritems() 不把dict转换成list,而是在迭代过程中不断给出 tuple,所以, iteritems() 不占用额外的内存:
-
小练习:请根据dict:
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59, 'Paul': 74 }
打印出 name : score,最后再打印出平均分 average : score。
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59, 'Paul': 74 }
sum = 0.0
for k, v in d.iteritems():
sum = sum + v
print k,':',v
print 'average', ':', sum/len(d)
61. 生成列表
- 要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我们可以用range(1, 11):
>>> range(1, 11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- 生成[1x1, 2x2, 3x3, ..., 10x10]怎么做:
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 写列表生成式时,把要生成的元素 x * x 放到前面,后面跟 for 循环,就可以把list创建出来
- 小练习:请利用列表生成式生成列表 [1x2, 3x4, 5x6, 7x8, ..., 99x100]
提示:range(1, 100, 2) 可以生成list [1, 3, 5, 7, 9,...]:
print [x*(x+1) for x in range(1,101,2)]
62. 复杂表达式
- for循环的迭代不仅可以迭代普通的list,还可以迭代dict。
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
可以通过一个复杂的列表生成式把它变成一个 HTML 表格:
tds = ['<tr><td>%s</td><td>%s</td></tr>' % (name, score) for name, score in d.iteritems()]
print '<table>'
print '<tr><th>Name</th><th>Score</th><tr>'
print '\n'.join(tds)
print '</table>'
# 注:字符串可以通过 % 进行格式化,用指定的参数替代 %s。字符串的join()方法可以把一个 list 拼接成一个字符串
<table border="1">
<tr><th>Name</th><th>Score</th><tr>
<tr><td>Lisa</td><td>85</td></tr>
<tr><td>Adam</td><td>95</td></tr>
<tr><td>Bart</td><td>59</td></tr>
</table>
- 小练习:任务
在生成的表格中,对于没有及格的同学,请把分数标记为红色。提示:红色可以用 <td style="color:red"> 实现。
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
def generate_tr(name, score):
if score < 60 :
return '<tr><td>%s</td><td style="color:red">%s</td></tr>' % (name, score)
return '<tr><td>%s</td><td>%s</td></tr>' % (name, score)
tds = [generate_tr(name, score) for name, score in d.iteritems()]
print '<table border="1">'
print '<tr><th>Name</th><th>Score</th><tr>'
print '\n'.join(tds)
print '</table>'
63. 条件过滤
- 列表生成式的 for 循环后面还可以加上 if 判断:
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
- 如果我们只想要偶数的平方,不改动 range()的情况下,可以加上 if 来筛选:
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
- 小练习:
请编写一个函数,它接受一个 list,然后把list中的所有字符串变成大写后返回,非字符串元素将被忽略。
提示:- isinstance(x, str) 可以判断变量 x 是否是字符串;
- 字符串的 upper() 方法可以返回大写的字母。
def toUppers(L):
return [x.upper() for x in L if isinstance(x, str)]
print toUppers(['Hello', 'world', 101])
64. 多层表达式
- for循环可以嵌套,因此,在列表生成式中,也可以用多层 for 循环来生成列表
L = []
for m in 'ABC':
for n in '123':
L.append(m + n)
>>> [m + n for m in 'ABC' for n in '123']
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
- 小练习:利用 3 层for循环的列表生成式,找出对称的 3 位数。例如,121 就是对称数,因为从右到左倒过来还是 121
# 百位的循环从 1-9,十位和个位的循环从 0-9
print [100 * n1 + 10 * n2 + n3 for n1 in range(1, 10) for n2 in range(10) for n3 in range(10) if n1==n3]
网友评论