不得不看的Python入门知识

Python最近很火,世界编程语言排行超过了Php!为什么这么火,为了一探究竟,打算把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的应用

  • Youtobe
  • 豆瓣
  • 闪电邮箱
  • 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. 数据类型

  • 整数:

    1. 整数的书写和数学一样,而且有负整数,如 0,-80
    2. 机器采用二进制,我们使用十六进制(0x开头,由0-9,a-f组成)表示整数更好,如 0x10,0xaf10
  • 浮点数:

    1. 浮点数就是小号:比如1.23,2.31,而对于很大或者很小的浮点数,就必须用科学计数法表示:把10用e替代,比如1.23x10^9就是1.23e9,再比如0.000012可以写成1.2e-5。
    2. 注意:整数和浮点数在计算机中的存储方式是不同的,整数的运算永远是精确的(除法也是精确的),而浮点数在运算中会有误差。
  • 字符串:字符串可以用单引号或者多引号包裹起来表示:”abc”,’abc’

  • 布尔值:

    1. 布尔值指的是true或者false
    2. 布尔值的运算可以通过运算符来进行:and(有false则false),or(有true则true),not(把true变为false或者false变为true)
  • 空值:空值用none表示,none不表示为0,0是有意义的,None是一个特殊的空值。

  • 练习:
    试一试,在右边编辑器中,完成以下任务:

    1. 计算十进制整数 45678 和十六进制整数 0x12fd2 之和。
    2. 请用字符串表示出Learn Python in imooc。
    3. 请计算以下表达式的布尔值(注意==表示判断是否相等):
      100 < 99
      0xff == 255
      注意:使用print命令
print 45678+0x12fd2
print "Learn Python in imooc"
print 100<99
123456
Learn Python in imooc
False

12. print语句

  1. 多个字符串可以用“,”逗号来进行连接,然后直接一起输出:
    (print 会依次打印每个字符串,遇到逗号就插入一个空格)
print 'hello','world','you','and','me'
hello world you and me
  1. 可以打印整数
print 300+500
800
  1. 注意(字符串、逗号、数学计算):
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解释器干了两件事情:
    1. 在内存中创建了一个’ABC’的字符串;
    2. 在内存中创建了一个名为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 发生,有两个办法:

    1. 先判断一下 key 是否存在,用 in 操作符:
if 'Paul' in d:
    print d['Paul']
  1. 使用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,valuelist
    123: '123',  # key 是 intvalue 是 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的特点

  1. set的内部结构和dict很像,唯一区别是不存储value,,因此,判断一个元素是否在set中速度很快。
  2. set存储的元素和dict的key类似,必须是不变对象,因此,任何可变对象是不能放入set中的.
  3. 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中删除。

    1. 增加:set的add()方法:
>>> s = set([1, 2, 3])
>>> s.add(4)
>>> print s
set([1, 2, 3, 4])
  1. 删除:set的remove()方法:
>>> s = set([1, 2, 3, 4])
>>> s.remove(4)
>>> print s
set([1, 2, 3])
  1. 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
>>> 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 循环总是可以依次取出集合的每一个元素
  • 集合是指包含一组元素的数据结构,我们已经介绍的包括:
    1. 有序集合:list,tuple,str和unicode;
    2. 无序集合:set
    3. 无序集合并且具有 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
    1. 迭代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
  • 不同之处:

    1. values() 方法实际上把一个 dict 转换成了包含 value 的list。
    2. 但是 itervalues() 方法不会转换,它会在迭代过程中依次从 dict 中取出 value,所以 itervalues() 方法比 values() 方法节省了生成 list 所需的内存。
    3. 打印 itervalues() 发现它返回一个 对象,这说明在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>
  • 小练习:任务
    在生成的表格中,对于没有及格的同学,请把分数标记为红色。提示:红色可以用 实现。
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中的所有字符串变成大写后返回,非字符串元素将被忽略。
    提示:
    1. isinstance(x, str) 可以判断变量 x 是否是字符串;
    2. 字符串的 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]
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值