列表
列表是Python中内置有序、可变序列,列表的所有元素放在一对中括号“[]”中,并使用逗号分隔开;
当列表元素增加或删除时,列表对象自动进行扩展或收缩内存,保证元素之间没有缝隙;
在Python中,一个列表中的数据类型可以各不相同,可以同时分别为整数、实数、字符串等基本类型,甚至是列表、元组、字典、集合以及其他自定义类型的对象。
常用方法
方法
说明
lst.append(x)
将元素x添加至列表lst尾部
lst.extend(L)
将列表L中所有元素添加至列表lst尾部
lst.insert(index, x)
在列表lst指定位置index处添加元素x,该位置后面的所有元素后移一个位置
lst.remove(x)
在列表lst中删除首次出现的指定元素,该元素之后的所有元素前移一个位置
lst.pop([index])
删除并返回列表lst中下标为index(默认为-1)的元素
lst.clear()
删除列表lst中所有元素,但保留列表对象
lst.index(x)
返回列表lst中第一个值为x的元素的下标,若不存在值为x的元素则抛出异常
lst.count(x)
返回指定元素x在列表lst中的出现次数
lst.reverse()
对列表lst所有元素进行逆序
lst.sort(key=None, reverse=False)
对列表lst中的元素进行排序,key用来指定排序依据,reverse决定升序(False)还是降序(True)
lst.copy()
返回列表lst的浅复制
列表推导式
列表推导式在内部实际上是一个循环结构,只是形式更加简洁,例如:
aList = [x*x for x in range(10)]
相当于
aList = []
for x in range(10): aList.append(x*x)
过滤不符合条件的元素
aList = [-1,-4,6,7.5,-2.3,9,-11]
[i for i in aList if i>0]
[6, 7.5, 9]
元组
元组和列表类似,但属于不可变序列,元组一旦创建,用任何方法都不可以修改其元素。 元组的定义方式和列表相同,但定义时所有元素是放在一对圆括号“()”中,而不是方括号中。
与列表的区别
元组一旦定义就不允许更改
元组没有append()、extend()和insert()等方法,无法向元组中添加元素
元组没有remove()或pop()方法,也无法对元组元素进行del操作,不能从元组中删除元素
从效果上看,tuple( )冻结列表,而list( )融化元组
优点
元组的速度比列表更快
如果定义了一系列常量值,而所需做的仅是对它进行遍历,那么一般使用元组而不用列表。
元组对不需要改变的数据进行“写保护”将使得代码更加安全。 元组可用作字典的“键”,也可以作为集合的元素
列表永远不能当做字典键使用,也不能作为集合的元素,因为列表不是不可变的
字典
字典是无序、可变序列。 定义字典时,每个元素的键和值用冒号分隔,元素之间用逗号分隔,所有的元素放在一对大括号“{}”中。 字典中的键可以为任意不可变数据,比如整数、实数、复数、字符串、元组等等。 globals()返回包含当前作用域内所有全局变量和值的字典 locals()返回包含当前作用域内所有局部变量和值的字典
创建
使用=将一个字典赋值给一个变量
a_dict = {‘server’: ‘db.diveintopython3.org’, ‘database’: ‘mysql’}
a_dict {‘database’: ‘mysql’, ‘server’: ‘db.diveintopython3.org’}
x = {} #空字典
x {}
使用dict利用已有数据创建字典
keys = [‘a’, ‘b’, ‘c’, ‘d’]
values = [1, 2, 3, 4]
dictionary = dict(zip(keys, values))
dictionary {‘a’: 1, ‘c’: 3, ‘b’: 2, ‘d’: 4}
x = dict() #空字典
x {}
元素获取
以键作为下标可以读取字典元素,若键不存在则抛出异常
使用字典对象的get方法获取指定键对应的值,并且可以在键不存在的时候返回指定值
使用字典对象的items()方法可以返回字典的键、值对
使用字典对象的keys()方法可以返回字典的键
使用字典对象的values()方法可以返回字典的值
元素添加
当以指定键为下标为字典赋值时:
1)若键存在,则可以修改该键的值;
2)若不存在,则表示添加一个键、值对。
aDict[‘age’] = 38 #修改元素值
aDict {‘age’: 38, ‘name’: ‘Dong’, ‘sex’: ‘male’}
aDict[‘address’] = ‘SDIBT’ #增加新元素
aDict {‘age’: 38, ‘address’: ‘SDIBT’, ‘name’: ‘Dong’, ‘sex’: ‘male’}
元素删除
使用del删除字典中指定键的元素
使用字典对象的clear()方法来删除字典中所有元素
使用字典对象的pop()方法删除并返回指定键的元素
使用字典对象的popitem()方法删除并返回字典中的一个元素
字典推导式
s = {x:x.strip() for x in (’ he ', 'she ‘, ’ I’)}
s
{’ he ‘: ‘he’, ’ I’: ‘I’, 'she ': ‘she’}
集合
集合是无序、可变序列,使用一对大括号界定,元素不可重复,同一个集合中每个元素都是唯一的。 集合中只能包含数字、字符串、元组等不可变类型(或者说可哈希)的数据,而不能包含列表、字典、集合等可变类型的数据。
创建
直接将集合赋值给变量
a = {3, 5}
a.add(7) #向集合中添加元素
a {3, 5, 7}
使用set将其他类型数据转换为集合
a_set = set(range(8,14))
a_set {8, 9, 10, 11, 12, 13}
b_set = set([0, 1, 2, 3, 0, 1, 2, 3, 7, 8]) #自动去除重复
b_set {0, 1, 2, 3, 7, 8}
c_set = set() #空集合
c_set set()
使用del删除整个集合
当不再使用某个集合时,可以使用del命令删除整个集合。集合对象的pop()方法弹出并删除其中一个元素,remove()方法直接删除指定元素,clear()方法清空集合。
切片
切片适用于列表、元组、字符串、range对象等类型,但作用于列表时功能最强大。可以使用切片来截取列表中的任何部分,得到一个新列表,也可以通过切片来修改和删除列表中部分元素,甚至可以通过切片操作为列表对象增加元素。
切片使用2个冒号分隔的3个数字来完成
第一个数字表示切片开始位置(默认为0)
第二个数字表示切片截止(但不包含)位置(默认为列表长度)
第三个数字表示切片的步长(默认为1),当步长省略时可以顺便省略最后一个冒号
切片操作不会因为下标越界而抛出异常,而是简单地在列表尾部截断或者返回一个空列表,代码具有更强的健壮性。
aList = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
aList[::] #返回包含所有元素的新列表 [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
aList[::-1] #逆序的所有元素 [17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
aList[::2] #偶数位置,隔一个取一个 [3, 5, 7, 11, 15]
aList[1::2] #奇数位置,隔一个取一个 [4, 6, 9, 13, 17]
aList[3::] #从下标3开始的所有元素 [6, 7, 9, 11, 13, 15, 17]
aList[3:6] #下标在[3, 6)之间的所有元素 [6, 7, 9]
aList[0?1] #前100个元素,自动截断 [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
aList[100:] #下标100之后的所有元素,自动截断 []
aList[100] #直接使用下标访问会发生越界 IndexError: list index out of range
切片返回的是列表元素的浅复制,所谓浅复制,是指生成一个新的列表,并且把原列表中所有元素的引用都复制到新列表中。如果原列表中只包含整数、实数、复数等基本类型或元组、字符串这样的不可变类型的数据,一般是没有问题的。如果原列表中包含列表之类的可变数据类型,由于浅复制时只是把子列表的引用复制到新列表中,这样的话修改任何一个都会影响另外一个。
序列解包
可以使用序列解包功能对多个变量同时赋值
x, y, z = 1, 2, 3 #多个变量同时赋值
v_tuple = (False, 3.5, ‘exp’)
(x, y, z) = v_tuple
x, y, z = v_tuple
x, y, z = range(3) #可以对range对象进行序列解包
x, y, z = iter([1, 2, 3]) #使用迭代器对象进行序列解包
x, y, z = map(str, range(3)) #使用可迭代的map对象进行序列解包
a, b = b, a #交换两个变量的值
x, y, z = sorted([1, 3, 2]) #sorted()函数返回排序后的列表
a, b, c = ‘ABC’ #字符串也支持序列解包
x = [1, 2, 3, 4, 5, 6]
x[:3] = map(str, range(5)) #切片也支持序列解包
x [‘0’, ‘1’, ‘2’, ‘3’, ‘4’, 4, 5, 6]
序列解包遍历多个序列
keys = [‘a’, ‘b’, ‘c’, ‘d’]
values = [1, 2, 3, 4]
for k, v in zip(keys, values): print((k, v), end=’ ')
(‘a’, 1) (‘b’, 2) (‘c’, 3) (‘d’, 4)
字符串
格式化
格式字符
说明
%s
字符串 (采用str()的显示)
%r
字符串 (采用repr()的显示)
%c
单个字符
%d
十进制整数
%i
十进制整数
%o
八进制整数
%x
十六进制整数
%e
指数 (基底写为e)
%E
指数 (基底写为E)
%f、%F
浮点数
%g
指数(e)或浮点数 (根据显示长度)
%G
指数(E)或浮点数 (根据显示长度)
%%
一个字符"%"
常用方法
find()、rfind()、index()、rindex()、count()
find()和rfind方法分别用来查找一个字符串在另一个字符串指定范围(默认是整个字符串)中首次和最后一次出现的位置,如果不存在则返回-1;
index()和rindex()方法用来返回一个字符串在另一个字符串指定范围中首次和最后一次出现的位置,如果不存在则抛出异常;
count()方法用来返回一个字符串在当前字符串中出现的次数。
split()、rsplit()、partition()、rpartition()
split()和rsplit()方法分别用来以指定字符为分隔符,把当前字符串从左往右或从右往左分隔成多个字符串,并返回包含分隔结果的列表;
partition()和rpartition()用来以指定字符串为分隔符将原字符串分隔为3部分,即分隔符前的字符串、分隔符字符串、分隔符后的字符串,如果指定的分隔符不在原字符串中,则返回原字符串和两个空字符串。
不推荐使用+运算符连接字符串,优先使用join()方法。
lower()、upper()、capitalize()、title()、swapcase()
s = “What is Your Name?”
s.lower() #返回小写字符串 ‘what is your name?’
s.upper() #返回大写字符串 ‘WHAT IS YOUR NAME?’
s.capitalize() #字符串首字符大写 ‘What is your name?’
s.title() #每个单词的首字母大写 ‘What Is Your Name?’
s.swapcase() #大小写互换 ‘wHAT IS yOUR nAME?’
查找替换replace(),类似于Word中的“全部替换”功能。
strip()、rstrip()、lstrip()
s = " abc "
s.strip() #删除空白字符 ‘abc’
‘\n\nhello world \n\n’.strip() #删除空白字符 ‘hello world’
“aaaassddf”.strip(“a”) #删除指定字符 ‘ssddf’
“aaaassddf”.strip(“af”) ‘ssdd’
“aaaassddfaaa”.rstrip(“a”) #删除字符串右端指定字符 ‘aaaassddf’
“aaaassddfaaa”.lstrip(“a”) #删除字符串左端指定字符 ‘ssddfaaa’
s.startswith(t)、s.endswith(t),判断字符串是否以指定字符串开始或结束
isalnum()、isalpha()、isdigit()、isdecimal()、isnumeric()、isspace()、isupper()、islower(),用来测试字符串是否为数字或字母、是否为字母、是否为数字字符、是否为空白字符、是否为大写字母以及是否为小写字母。
异常
简单地说,异常是指程序运行时引发的错误,引发错误的原因有很多,例如除零、下标越界、文件不存在、网络异常、类型错误、名字错误、字典键错误、磁盘空间不足,等等。 如果这些错误得不到正确的处理将会导致程序终止运行,而合理地使用异常处理结构可以使得程序更加健壮,具有更强的容错性,不会因为用户不小心的错误输入或其他运行时原因而造成程序终止。 也可以使用异常处理结构为用户提供更加友好的提示。 程序出现异常或错误之后是否能够调试程序并快速定位和解决存在的问题也是程序员综合水平和能力的重要体现方式之一。
可以继承Python内置异常类来实现自定义的异常类。如果try范围内捕获了异常,就执行except块;如果try范围内没有捕获异常,就执行else块。
try…except…finally结构,finally子句中的内容无论是否发生异常都会执行,常用来做一些清理工作以释放try子句中申请的资源。
class ShortInputException(Exception):
def init(self, length, atleast):
Exception.init(self)
self.length = length
self.atleast = atleast
try:
s = input('请输入 --> ')
if len(s) < 3:
raise ShortInputException(len(s), 3)
except ShortInputException as x:
print(‘ShortInputException: 长度是 %d, 至少应是 %d’ % (x.length, x.atleast))
else: print (‘没有异常发生.’)
Requests 库
中文官方文档指引(https://2.python-requests.org//zh_CN/latest/user/quickstart.html)
pip安装requests
pip install requests
引入包
import requests
get或post请求
不带可选参数的get请求
r = requests.get(url=‘https://github.com/timeline.json’)
不带可选参数的post请求
r = requests.post(url=“http://httpbin.org/post”)
其他请求(直接路过,很少很少用到,本教程也不多讲)
r = requests.put(“http://httpbin.org/put”)
r = requests.delete(“http://httpbin.org/delete”)
r = requests.head(“http://httpbin.org/get”)
r = requests.options(“http://httpbin.org/get”)
1、get\post参数说明
http请求get与post是最常用的,url为必选参数,常用常用参数有params、data、json、files、timeout、headers、cookies;其他基本用不到的有verify,cert,auth,allow_redirects,proxies,hooks,stream。
下面列表对具体的参数说明:
重点在params、data、json、files、timeout,其次headers、cookies
preview
2、get请求文本与二进制数据内容(图片)
get请求是最简单的、发送的数据量比较小。
示例2.1:带多个参数的请求,返回文本数据
import requests
带参数的GET请求,timeout请求超时时间
params = {‘key1’: ‘python’, ‘key2’: ‘java’}
r = requests.get(url=‘http://httpbin.org/get’, params=params, timeout=3)
注意观察url地址,它已经将参数拼接起来
print(‘URL地址:’, r.url)
响应状态码,成功返回200,失败40x或50x
print(‘请求状态码:’, r.status_code)
print(‘header信息:’, r.headers)
print(‘cookie信息:’, r.cookies)
print(‘响应的数据:’, r.text)
如响应是json数据 ,可以使用 r.json()自动转换为dict
print(‘响应json数据’, r.json())
示例2.2:get返回二进制数据,如图片。
from PIL import Image
from io import BytesIO
import requests
请求获取图片并保存
r = requests.get(‘https://pic3.zhimg.com/247d9814fec770e2c85cc858525208b2_is.jpg’)
i = Image.open(BytesIO(r.content))
i.show() # 查看图片
将图片保存
with open(‘img.jpg’, ‘wb’) as fd:
for chunk in r.iter_content():
fd.write(chunk)
注意: PIL 无法使用请安装pip install pillow
3、post请求,上传表单,文本,文件\图片
post请求比get复杂,请求的数据有多种多样,有表单(form-data),文本(json\xml等),文件流(图片\文件)等。
表单形式提交的post请求,只需要将数据传递给post()方法的data参数。见示例3.1.
json文本形式提交的post请求,一种方式是将json数据dumps后传递给data参数,另一种方式就是直接将json数据传递给post()方法的json参数。见示例3.2.
单个文件提交的post请求,将文件流给post()方法的files参数。见示例3.3。
多个文件提交的post请求,将文件设到一个元组的列表中,其中元组结构为 (form_field_name, file_info);然后将数据传递给post()方法的files。见示例3.4.
示例3.1:post 表单请求
import requests, json
带参数表单类型post请求
data={‘custname’: ‘woodman’,‘custtel’:‘13012345678’,‘custemail’:‘woodman@11.com’,
‘size’:‘small’}
r = requests.post(‘http://httpbin.org/post’, data=data)
print(‘响应数据:’, r.text)
示例3.2:post json请求
json数据请求
url = ‘https://api.github.com/some/endpoint’
payload = {‘some’: ‘data’}
可以使用json.dumps(dict) 对编码进行编译
r = requests.post(url, data=json.dumps(payload))
print(‘响应数据:’, r.text)
可以直接使用json参数传递json数据
r = requests.post(url, json=payload)
print(‘响应数据:’, r.text)
示例3.3:post提交单个文件
上传单个文件
url = ‘http://httpbin.org/post’
注意文件打开的模式,使用二进制模式不容易发生错误
files = {‘file’: open(‘report.txt’, ‘rb’)}
也可以显式地设置文件名,文件类型和请求头
files = {‘file’: (‘report.xls’, open(‘report.xls’, ‘rb’), ‘application/vnd.ms-excel’, {‘Expires’: ‘0’})}
r = requests.post(url, files=files)
r.encoding = ‘utf-8’
print(r.text)
注意:文件的上传使用二进制打开不容易报错。
示例3.4:上传多个文件
url = ‘http://httpbin.org/post’
multiple_files = [
(‘images’, (‘foo.png’, open(‘foo.png’, ‘rb’), ‘image/png’)),
(‘images’, (‘bar.png’, open(‘bar.png’, ‘rb’), ‘image/png’))]
r = requests.post(url, files=multiple_files)
print(r.text)
示例3.5:拓展,将字符串作为文件上传
可以把字符串当着文件进行上传,只能用显示设置文件名上传
url = ‘http://httpbin.org/post’
files = {‘file’: (‘report.csv’, ‘some,data,to,send\nanother,row,to,send\n’)}
r = requests.post(url, files=files)
print(r.text)
4、get与post请求的header与cookie管理
获取get与post请求响应的header与cookie分别使用r.headers与r.cookies。如果提交请求数据是对header与cookie有修改,需要在get()与post()方法中加入headers或cookies参数,它们值的类型都是字典。
示例4.1:定制请求头header
import requests
url = ‘https://api.github.com/some/endpoint’
headers = {‘user-agent’: ‘my-app/0.0.1’}
r = requests.get(url, headers=headers)
print(r.headers) # 获取响应数据的header信息
注意:requests自带headers管理,一般情况下不需要设置header信息。Requests 不会基于定制 header 的具体情况改变自己的行为。只不过在最后的请求中,所有的 header 信息都会被传递进去。
示例4.2:定制cookie信息
直接以字典型时传递cookie
url = ‘http://httpbin.org/cookies’
cookies = {“cookies_are”:‘working’}
r = requests.get(url, cookies=cookies)
获取响应的cookie信息,返回结果是RequestsCookieJar对象
print(r.cookies)
print(r.text)
import requests.cookies
我们也可以使用 RequestsCookieJar 对象提交cookies信息
jar = requests.cookies.RequestsCookieJar()
jar.set(‘tasty_cookie’, ‘yum’, domain=‘httpbin.org’, path=’/cookies’)
jar.set(‘gross_cookie’, ‘blech’, domain=‘httpbin.org’, path=’/elsewhere’)
url = ‘http://httpbin.org/cookies’
r = requests.get(url, cookies=jar)
print(r.text)
注意:RequestsCookieJar传递cookies信息,它的行为和字典类似,它非常适合跨域名跨路径使用。
5、session与cookie存储
如果你向同一主机发送多个请求,每个请求对象让你能够跨请求保持session和cookie信息,这时我们要使用到requests的Session()来保持回话请求的cookie和session与服务器的相一致。
示例5.1:创建一个session会话:
s = requests.Session()
session会话的get与post请求
不带可选参数的get请求
r = s.get(url=‘https://github.com/timeline.json’)
不带可选参数的post请求
r = s.post(url=“http://httpbin.org/post”)
session会话对象的get与post请求参数与requests()的get与post请求参数一致。
session会话还可以用作with前后文管理器:
示例5.2:
with requests.Session() as s:
s.get(‘http://httpbin.org/cookies/set/sessioncookie/123456789’)
这样能确保 with 区块退出后会话能被关闭,即使发生了异常也一样。
requests的session会话需要注意的是会话方法级别的参数也不会被跨请求保持。
如下示例5.3:
s = requests.Session()
r = s.get(‘http://httpbin.org/cookies’, cookies={‘from-my’: ‘browser’})
print(r.text)
‘{“cookies”: {“from-my”: “browser”}}’
r = s.get(‘http://httpbin.org/cookies’)
print(r.text)
‘{“cookies”: {}}’
第一个get请求中加入方法级别cookies参数,在第二个get请求中不会保持第一个get请求的cookies参数。
6、requests请求返回对象Response的常用方法
requests.get(url)与requests.post(url)的返回对象为Response 类对象。
Response响应类常用属性与方法:
Response.url 请求url,[见示例2.1]
Response.status_code 响应状态码,[见示例2.1]
Response.text 获取响应内容,[见示例2.1]
Response.json() 活动响应的JSON内容,[见示例2.1]
Response.ok 请求是否成功,status_code<400 返回True
Response.headers 响应header信息,[见示例2.1]
Response.cookies 响应的cookie,[见示例2.1]
Response.elapsed 请求响应的时间。
Response.links 返回响应头部的links连接,相当于Response.headers.get(‘link’)
Response.raw 获取原始套接字响应,需要将初始请求参数stream=True
Response.content 以字节形式获取响应提,多用于非文本请求,[见示例2.2]
Response.iter_content() 迭代获取响应数据,[见示例2.2]
Response.history 重定向请求历史记录
Response.reason 响应状态的文本原因,如:“Not Found” or “OK”
Response.close() 关闭并释放链接,释放后不能再次访问’raw’对象。一般不会调用。
示例5.1:
import requests
r = requests.get(‘http://github.com’, stream=True)
print(‘状态码:’,r.status_code)
print(‘请求是否成功:’,r.ok)
print(‘响应提文本内容:’,r.reason)
print(‘重定向历史:’,r.history)
print(‘header的link:’,r.links)
print(‘响应时长:’,r.elapsed)
r.raw 获取到内容,请求时将stream设为True
print(‘原始套接字响应:’,r.raw)
print(‘原始套接字响应:’,r.raw.read())
Python DB API
文件操作
用于文件内容读写时,with语句的用法如下:
with open(filename, mode, encoding) as fp: #这里写通过文件对象fp读写文件内容的语句
另外,上下文管理语句with还支持下面的用法,进一步简化了代码的编写:
with open(‘test.txt’, ‘r’) as src, open(‘test_new.txt’, ‘w’) as dst:
dst.write(src.read())
文件打开方式
模式
说明
r
读模式(默认模式,可省略),如果文件不存在则抛出异常
w
写模式,如果文件已存在,先清空原有内容
x
写模式,创建新文件,如果文件已存在则抛出异常
a
追加模式,不覆盖文件中原有内容
b
二进制模式(可与其他模式组合使用)
t
文本模式(默认模式,可省略)
读、写模式(可与其他模式组合使用)
文件对象常用属性
方法
功能说明
close()
把缓冲区的内容写入文件,同时关闭文件,并释放文件对象
detach()
分离并返回底层的缓冲,底层缓冲被分离后,文件对象不再可用,不允许做任何操作
flush()
把缓冲区的内容写入文件,但不关闭文件
read([size])
从文本文件中读取size个字符(Python 3.x)的内容作为结果返回,或从二进制文件中读取指定数量的字节并返回,如果省略size则表示读取所有内容
readable()
测试当前文件是否可读
readline()
从文本文件中读取一行内容作为结果返回
readlines()
把文本文件中的每行文本作为一个字符串存入列表中,返回该列表,对于大文件会占用较多内存,不建议使用
seek(offset[, whence])
把文件指针移动到新的位置,offset表示相对于whence的位置。whence为0表示从文件头开始计算,1表示从当前位置开始计算,2表示从文件尾开始计算,默认为0
seekable()
测试当前文件是否支持随机访问,如果文件不支持随机访问,则调用方法seek()、tell()和truncate()时会抛出异常
tell()
返回文件指针的当前位置
truncate([size])
删除从当前指针位置到文件末尾的内容。如果指定了size,则不论指针在什么位置都只留下前size个字节,其余的一律删除
write(s)
把s的内容写入文件
writable()
测试当前文件是否可写
writelines(s)
把字符串列表写入文本文件,不添加换行符