- 参考书《Python基础教程(第三版)》—— Magnus Lie Hetland
文章目录
一、再看print和import
1. print()函数
- 原型
print( para,para,..,(sep = para),(end = para) ):none
- print()可以打印一个表达式,这个表达式要么是字符串,要么自动转为字符串形式打印
- print()中可以填任意多个参数,关键字实参
sep
和end
可以缺省sep
指定打印的两个参数间的间隔符,缺省为空格' '
end
指定打印的字符串的后缀,缺省为换行符'\n'
#缺省sep和end
>>> print('A',1,2)
A 1 2
#设置sep为'_'
>>> print('A',1,2,sep = '_')
A_1_2
#设置sep和end
>>> print('A',1,2,sep = '_',end = '*')
A_1_2*
#end尾缀可以是字符串
>>> print('A',1,2,sep = '_',end = 'AAAA')
A_1_2AAAA
2. import
-
从模块导入
- 导入一个模块:
import 模块名
- 调用方法/函数:
模块名.方法/函数名()
,这里是方法/函数的引用 - 访问属性:
模块名.属性名
,这里是原属性的引用
- 调用方法/函数:
- 导入一个模块中的所有属性和方法/函数:
from 模块名 import *
- 调用方法/函数:
方法/函数名()
,这里是方法/函数的引用 - 访问属性:
属性名
,这里是原属性的拷贝
- 调用方法/函数:
- 导入某个方法:
from 模块名 import 方法名
- 导入某几个方法:
from 模块名 import 方法名1,方法名2,方法名3
- 导入一个模块:
-
如果有两个模块包含一样的方法名(如open)
- 给模块起别名:
improt 模块名 as 别名
- 给方法起别名:
from 模块名 import 方法名 as 别名
- 给模块起别名:
二、特殊赋值方法
1. 序列解包
- 序列解包:将一个序列或任何可迭代对象解包,并将得到的值存储到一系列变量中
>>> values = 1,2,3
>>> values
(1, 2, 3)
#对元组进行解包
>>> x,y,z = values
>>> x,y,z
(1, 2, 3)
>>> x
1
>>> x,y
(1,2)
#利用序列解包交换变量值
>>> x,y = y,x
>>> x,y,z
(2, 1, 3)
- 序列解包在使用返回元组(或其他数列、可迭代对象啊)的函数/方法时很有用
>>> items = {'name': 'Tom', 'age': 18}
>>> key,value = items.popitem() #字典的popitem()方法,任意弹出字典中一个键值对
>>> key
'age'
>>> value
18
- 收集参数
- 使用序列解包时,要确保左边给出的目标数目和被解包序列元素个数相同,否则出错
- 用 “带*变量” 收集多余的序列元素,这样带*变量得到一个列表
- 这种方法可以用到函数参数列表中
>>> A,B = [1,2,3,4] #报错
>>> A,B,*rest = [1,2,3,4]
>>> rest
>>> [3,4]
>>> A,B,*rest = [1,2,3]
>>> rest
>>> [3]
>>> A,*rest,B = [1,2,3,4,5]
>>> rest
>>> [2,3,4]
2. 链式赋值
x = y = somefunction()
#等价于
y = somefunction()
x = y
3. 增强赋值
- 可以使用
+=
和-=
,类似C++
>>> a = 10
>>> a += 2
>>> a
12
>>> str = 'ABC'
>>> str += 'D'
>>> str
'ABCD'
三、条件和条件语句 if-elif-else
1. 布尔值
- 标准真值是
True/False
,它们是1和0的别名
>>> True+1
2
>>> False == 0
True
-
用作布尔表达式时
- 以下被解释为False:
False
/None
/0
/''
/()
/[]
/{}
- 其他被解释为True
- 以下被解释为False:
-
bool和list一样,可以用来转换其他值构造bool类型
>>> bool("ABC")
>>> True
>>> bool('')
False
2. 条件语句
if-elif-else
结构
if expression1:
# code
elif expression2:
# code
...
elif expressionN:
# code
else:
# code
3. 布尔表达式
- 比较运算符
符号 | 说明 | |
---|---|---|
传统比较运算符 | == / != / > / < / >= / <= | 类似C/C++中的比较符号 |
链式比较 | 1 <= number <= 10 | 等价于1 <= number && number <= 10 |
对象比较 | is / is not | 比较两个对象是否为同一个对象;而== 比较两个对象是否相等 (不可将is用于比较数和字符串等不可改变的基本值,鉴于python在内部处理这些对象的方式,这样做的结果是不可预测的) |
成员资格检查 | in / not in | 如x in y 检查x是否为容器y的成员 |
# '=='检查两个对象是否相等
# 'is'检查两个对象是否相同(“指向同一个对象” / 或者时说“是同一个对象”)
>>> x = y = [1,2,3] # 等价于y = [1,2,3], x = y
>>> z = [1,2,3]
>>> x == y
True
>>> x == z
True
>>> x is y
True
>>> x is z
False
- 字符串和序列的比较
-
字符串是根据字符的字母排序进行比较的
-
本质上比较的是unicode编码,字符是按码点排列的
- 可以用ord(char)返回字符的Unicode值
- 可以用chr(int)将Unicode值转为字符返回
-
序列的比较方式也是这样的
-
>>> ord('A')
65
>>> chr(65)
'A'
>>> [1,2]<[2,1]
True
>>> [2,[1,4]]<[2,[1,5]]
True
-
逻辑运算符
- 逻辑运算符用来连接多个布尔表达式,构成复合条件表达式
- python中的逻辑运算符:
and / or / not
- python的符合条件语句也有短路特性
运算符 操作 说明 and
与运算 类似C中 &&
or
或运算 类似C中 ||
not
非运算 类似C中 !
4. 断言
- 断言是if的“亲戚”,伪代码类似如下:
# 断言的伪代码
if not condition:
crash program
-
断言的目的在于在程序出错时立刻崩溃,而不是错误隐藏到之后再崩溃
-
基本上,可以用断言要求某些条件得到满足,比如判断参数合法
-
断言的形式
assert 条件表达式 (,'报错字符串')
# 条件满足,断言报错不被触发
>>> age = 10
>>> assert 0 < age < 100
# 条件不满足,触发断言报错
>>> age = -1
>>> assert 0 < age < 100
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
#可以在assert断言后加一个说明字符串,这样报错的时候可以看到说明
>>> age = -1
>>> assert 0 < age < 100, "Age Error"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: Age Error
四、循环语句
1. while循环
while 判断条件:
循环体
2. for循环
- 基本上,可迭代对象是可以用for循环遍历的对象。(后面再介绍迭代器,目前把可迭代对象视为序列即可)
# 遍历列表打印
words = ['apple','big','car']
for word in words:
print(word)
numbers = [1,2,3,4,5,6,7,8,9,10]
for num in numbers:
print(num)
- 为了方便遍历特定范围的数据,python提供内置函数
range(begin,end)
>>> range(0,10)
range(0,10)
>>> list(range(0,10))
[0,1,2,3,4,5,6,7,8,9]
>>> list(range(5))
[0,1,2,3,4,5]
- 还可以加上步进长度参数
range(begin,end,step)
>>> list(range(10,0,-1))
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> list(range(10,0,-2))
[10, 8, 6, 4, 2]
>>> list(range(10,0,-3))
[10, 7, 4, 1]
- 可以用类似序列的方法用for循环遍历字典,但是字典内部是没有顺序的,所有这样for循环打印的顺序是不一定的,只能保证所有值都被处理。如果顺序很重要,可以把键或值存入一个列表,对列表进行排序,再迭代
#打印所有键值对
d = {'x':1,'y':2 }
for key in d:
print(key,":",d[key])
#打印所有键值对(使用了序列解包)
d = {'x':1,'y':2 }
for key,value in d.items():
print(key,":",value)
3. 迭代工具
- python提供了一系列可以帮助迭代的函数,其中一些位于
itertools
模块中,另外还有一些内置函数
(1)并行迭代 zip()
- 有时候可能想并行迭代两个序列,可以用
zip(a,b,c...)
把任意多个序列"缝合"起来,并返回一个由元组组成的序列。可以把它转换为列表查看 - 当被缝合的序列长度不同时,zip将只缝合并返回最短序列长度个元素
>>> list1 = [1,2,3]
>>> list2 = ['A','B','C']
>>> list3 = [4,5,6,7,8,9]
>>> list(zip(list1,list2,list3))
[(1, 'A', 4), (2, 'B', 5), (3, 'C', 6)]
- zip配合序列解包,可以方便地进行多序列并行迭代
#不使用zip
names = ['Tom','Bill','Jack']
ages = [12,20,18]
for i in range(len(names)):
print(names[i],'is',ages[i],'years old')
#使用zip
names = ['Tom','Bill','Jack']
ages = [12,20,18]
for name,age in zip(names,ages):
print(name,'is',age,'years old')
(2)迭代时获取索引
- 利用
enumerate(可迭代对象)
函数:返回一个由元组组成的序列,每个元组是由索引和元素值组成,用list()可以把这个序列转为元组列表。
>>> list(enumerate(['A','B','C','D']))
[(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D')]
>>> list(enumerate('string'))
[(0, 's'), (1, 't'), (2, 'r'), (3, 'i'), (4, 'n'), (5, 'g')]
# 一个示例 ------------------------
lst = ['BBC','CCTV','ABC']
for index,item in enumerate(lst):
if 'B' in item:
lst[index] = 'X'
print(lst) # 打印['X', 'CCTV', 'X']
(3)反向迭代和排序后再迭代
- python提供了两个内置函数
reversed(可迭代对象):list_reverseiterator object
和sorted(可迭代对象):list
,它们不修改原对象,而是返回反转后的“列表反向迭代对象”和“排序后的列表”
lst = [4,3,5,7,6,5]
print(list(reversed(lst))) #打印[5, 6, 7, 5, 3, 4]
print(sorted(lst)) #打印[3, 4, 5, 5, 6, 7]
- 注意:
sorted()
返回一个列表,而reversed()
返回一个类似zip的更神秘的可迭代对象,我们不必关心这个到底意味着什么,在for循环或join等方法中使用完全没问题。但是不能对它进行索引或切片操作,也不能对它调用列表方法。要想当作列表一样用的话,可以用list()对返回对象进行转换
4. 跳出循环
- break(跳出循环)
#打印1~49
i = 1
while i<100:
if i == 50:#打印到50时跳出
break
print(i)
i += 1
- continue(跳过本次循环)
#打印1 2 4 5
i = 1
while i <= 5:
if i == 3: #i==3时跳过
i += 1
continue
print(i)
i += 1
五、简单推导和字典推导
推到
不是语句,而是表达式- 列表推导是一种从其他列表创建列表的方法,类似集合推导,工作原理类似for循环
# 基本形式
>>> [x*x for x in range(10)]
[0,1,4,9,16,25,36,49,64,81,100]
# 增加一条if
>>>[x*x for x in range(10) if x % 3 == 0]
[0,9,36,81]
# 增加for
>>>[(x,y) for x in range(3) for y in range(4)]
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
# 也可同时加入更多的if和for
>>>[x*x for x in range(10) if x % 3 == 0 and x*x<10]
[0,9]
>>>[x*x for x in range(10) if x % 3 == 0 if x*x<10]#可以连写if代替复合条件
[0,9]
-
将上面的
[]
换成()
不能实现元组推导,这样做将创建生成器 -
可以用
{}
进行字典推导
>>> squares = {i:"{} squared is {}".format(i,i**2) for i in range(10)}
>>> squares[8]
'8 squared is 64'
六、其他语句del/pass/exec/eval
1. pass语句
- pass语句不做任何事
- pass可以用作占位符,因为python中的代码块不能为空,用pass填充代码块,可以让程序运行并测试已经写好的部分
flag = input()
if flag == '1':
print("...")
elif flag == '2': #分支没有写好,先跳过
pass
else:
print("xxx")
- 也可以插入一个字符串用作占位符,这种做法尤其适合未完成的函数和类,因为这种字符串将充当文档字符串
def fibs(num):
'lalalala' # 文档字符串(这个字符串会被作为函数的一部分储存起来)
result = [0,1]
for i in range(num-2):
result.append(result[-2]+result[-1])
return result
print(fibs.__doc__) # 打印lalalala
2. exec语句
- exec将字符串作为代码执行
>>> exec("print('Hello,world')")
Hello,world
- 大多数情况下,还应该向它传递一个命名空间——用于存放变量的地方,否则将污染命名空间(同名时覆盖原本代码中的变量或函数)
>>> from math import sqrt
>>> scope = {} # 定义一个字典作为命名空间
>>> exec('sqrt = 1',scope) # exec的第二个参数指出命名空间,否则这里的sqrt会污染从math导入的import
>>> sqrt(4) # 导入的sqrt正常运行
2.0
>>> scope['sqrt'] # 指定命名空间scope,通过exec执行赋值语句创建的变量位于scope中
1
- exec是一个过程,无返回值
- 注意
exec
可能引入不安全的代码
3. eval语句
- eval计算用字符串表示的Python表达式值,并返回结果
# 创建一个python计算器
>>> eval(input("Enter an arithmetic expression:"))
- 类似exec,也可以像eval提供命名空间
4. del语句
- python中带有垃圾回收机制,如果一个对象没有任何人引用,将会被自动回收
>>> d = dict([('name','Tom') , ('age',18)])
>>> d = None #这时刚刚创建的字典将被释放空间
del
语句也可以做到这一点,它不仅删除变量到对象的引用关系,还删除变量名称。但是del语句不会删除对象(事实上,python中无法手动释放对象,python的垃圾回收机制会自动释放不用的对象)
>>> x = [1,2,3]
>>> y = x
>>> del x
>>> y # 删除x后,对象没有消失,y仍然可引用;但若y也删除,列表对象被自动回收
[1,2,3]