目录
面向对象编程 Object-Oriented Programming(OOP)
基础必会
- 表达式
- 字面值
- 字符串 str
- 数字
- 整数 int
- 浮点数 float
- 布尔类型bool
- 容器
- 列表 list
- 元组 tuple
- 字典 dict
- 集合 set 和 固定集合 frozenset
- 字节串 bytes 和 字节数组bytearray(后面在学)- 运算符
- 算术运算符
+ - * / // % **
- 比较运算符
< > <= >= == !=
- 布尔运算符
and or not
L = [1, 2, 3, 4, 5, 6] print(L[2]) print(L[2:5])
- 条件表达式
'及格' if score >= 60 else '不及格'
- in / not in 运算符
'王昭君' in ['孙悟空', '赵云']
- 索引和切片
> 用于 str, list, tuple, bytes, bytearray
L = [1, 2, 3, 4, 5, 6] print(L[2]) print(L[2:5])
- 函数
- 构造函数(函数名和类名相同的函数)
str() ---> '' int() --> 0 float() bool() list() tuple() dict() set() frozenset()
- 函数
print() input() len(x) max(x) min(x) sum(x) range() type(x)
```- 语句
- 简单语句
- 表达式语句
- 赋值语句
- del 语句
- pass 语句
- break 语句
- contiue 语句
- 复合语句
- if 语句
- while 语句
- for 语句> 所有的容器类都是可迭代对象,可以用 for 语句遍历其中的全部内容
文字的编码
Python3的字符串内部存储的是文字的UNICODE编码
字符串中存储的是什么?
是一个图片(文字)对应的编码(code)
字符相关的函数
函数
说明
chr(x)
根据x的UNICODE编码值得到对应的字符
ord(x)
可以返回一个 字符的 UNICODE 编码值
英文的编码值 详见 ASCII 编码
man ascii
ord(x) 函数的返回值如果是0~127 则 x 是英文字符,中文字符串一个编码值一定大于128
示例
>>> chr(98) 'b' >>> chr(20000) '丠' >>> chr(20001) '両' >>> chr(20002) '丢' >>> chr(20003) '丣' >>> chr(20004) '两' >>> ord('两') 20004 >>> ord('A') # 65 >>> ord('B') # 66 # 英文的编码值在 0~127 之间 >>> ord('中') # 20013
- 在python的交互模式下打印全世界的文字
for ch in range(65536): print(chr(ch), end='')
函数定义 function
什么是函数
函数是可以重复执行的语句块,可以重复调用
作用
用于封装语句块, 提高代码的重用性。
函数是面向过程编程的最小单位
def 语句
作用
用来定义( 创建)函数
语法
def 函数名(形式参数列表): 语句块
- 说明
函数的名字就是语句块的名称
函数名必须是标识符
函数名是一个变量,不要轻易对其赋值
函数有自己的名字空间,在函数外部不可以访问函数内部的变量,在函数内部可以访问函数外部的变量,但不能轻易对其改变
函数的形参列表如果不需要传入参数,形式参数列表可以为空
示例
# 定义一个函数,用 say_hello 变量绑定 def say_hello(): print("hello world!") print("hello tarena!") print("hello everyone!") # 定义一个函数,传入两个参数,让这个函数把最大的值打印到终端 def mymax(a, b): if a > b: print("最大值是", a) else: print("最大值是", b)
函数的调用
语法
函数名(实际调用传递参数)
说明
函数调用是一个表达式
如果函数内没有return 语句,函数执行完毕后返回 None 对象
示例
# 调用 say_hello() # 调用一次 say_hello() # 调用第二次 # 调用 mymax(100, 200) mymax(999, 1) mymax('abc', 'cba')
return 语句
语法
return [表达式]
注: [] 代表 内部的内容可以省略
作用
用于函数的内部,结束当前函数的执行,返回到调用此函数的地方,同时返回一个对象的引用关系
说明
return 语句后面的表达式可以省略,省略后相当于 return None
如果函数内部没有 return 语句, 则函数执行完毕后返回None, 相当于在最后一条语句后有一条return None
示例
def say_hello(): print("hello aaa") print("hello bbb") return 1 + 2 print("hello ccc") r = say_hello() print(r) # 3
函数的调用传参
位置传参
实际参数传递时,实参和形参 按
位置
来依次对应关键字传参
实际参数传递时,实参和形参 按
名称
依次对应注: 位置传参要先于关键字传参
示例
def myfun1(a, b, c): print('a=', a) print('b=', b) print('c=', c) # 位置传参 myfun1(1, 2, 3) # 关键字传参 myfun1(c=33, a=11, b=22) # 位置传参要先于关键字传参 myfun1(111, c=333, b=222) # 正确
函数的形式参数定义方法
函数的缺省参数
语法
def 函数名(形参名1=默认实参1, 形参名2=默认实参2, ... ):
语句块说明
缺省参数必须自右向左依次存在(即,如果一个参数有缺省参数,则其右侧的所有参数都必须有缺省参数)
示例
def myadd4(a, b, c=0, d=0): return a + b + c + d print(myadd4(1, 2)) print(myadd4(1, 2, 3)) print(myadd4(1, 2, 3, 4)) 错误示例 >>> def myadd(a, b=0, c): # 报错 ... pass
形参的定义
位置形参
星号元组形参(*args)
命名关键字形参
双星号字典形参(**kwargs)
1) 位置形参
语法:
def 函数名(形参名1, 形参名2, ...): pass
2) 星号元组形参
语法
def 函数名(*元组形参名): pass
作用
收集多余的位置实参
元组形参名 一般命名为args
示例
def myfunc2(*args): print("len(args)=", len(args)) print('args=', args) myfunc2() # args=() myfunc2(1, 2, 3) # args=(1, 2, 3) def myfunc3(a, b, *args): print(a, b, args) myfunc3(1, 2) # 1-->a, 2-->b, ()--->args myfunc3(1, 2, 3, 4) # # 1-->a, 2-->b, (3, 4)--->args
3)命名关键字形参
语法
def 函数名(*, 命名关键字形参1, 命名关键字形参2, ...): pass # 或者 def 函数名(*args, 命名关键字形参1, 命名关键字形参2, ...): pass
作用
强制,所有的参数都必须用关键字传参
示例
def myfunc4(a, b,*args, c, d): print(a, b, c, d) myfunc4(1, 2, d=4, c=3) # 正确,c,d 必须关键字传参 myfunc4(1, 2, 3, 4) # 错误
4)双星号字典形参
语法
def 函数名(**字典形参名): pass
作用
收集多余的关键字传参
字典形参名 最多有一个,
字典形参名 一般命名为 kwargs
示例
def myfunc5(**kwargs): print(kwargs) # {'name': 'tarena', 'age': 18}-->kwargs myfunc5(name='tarena', age=18)
函数的形参定义方法说明
位置形参,星号元组形参,命名关键字参数,双星号字典形参,缺省参数可以混合使用。
函数的形参定义自左至右的顺序为:位置形参,星号元组形参,命名关键字参数,双星号字典形参
示例:
def fn(a, b, *args, c, d, **kwargs): pass fn(100, 200, 300, 400, c='C', e='E', d='D')
局部变量和全局变量
局部变量
定义在函数内部的变量称为局部变量(函数的形参也是局部变量)
局部变量只能在函数的内部使用
局部变量在函数调用时才能够被创建,在函数调用之后会自动销毁
全局变量
定义在函数外部,模块内部的变量称为全局变量
全局变量, 所有的函数都可以直接访问(取值,但函数内部不能直接将其赋值改变)
局部变量示例
>>> def fn(a, b): ... c= 100 ... print(a, b, c) # a, b, c三个都是局部变量 >>> fn(1, 2) >>> print(a, b, c) # 报错, 因为a,b,c 在调用后就销毁了
全局变量示例
a = 100 # 全局变量 def fx(b, c): # b,c 局部变量 d = 400 # d 局部变量 print(a, b, c, d) fx(200, 300) print(a) # 100 print(b) # 报错, 因为此时 b 不存在了
全局变量示例2
a = 100 # 全局变量 def fx(b): a = 666 # 创建局部变量,不是改变全局变量 c = 300 print(a, b, c) # 优先访问局部变量 fx(200) # 666 200 300 print(a) # 100
global 语句
问题
# 如何用一个变量来记录一个函数调用的次数 count = 0 def hello(name): print('hello', name) count += 1 # 等同于 count = count + 1 # 如何让 此语句能改变全局变量而不是创建局部变量 hello('小张') hello('小李') print('您共调用hello函数', count, '次') # 2 次
作用
告诉python 的解释执行器, global 语句声明的一个或多个变量, 这些变量是全局变量
语法
global 变量名1, 变量名2, ....
示例
# 如何用一个变量来记录一个函数调用的次数 count = 0 def hello(name): global count # 声明 global 是全局变量 print('hello', name) count += 1 # 等同于 count = count + 1 hello('小张') hello('小李') hello('小魏') print('您共调用hello函数', count, '次') # 3 次
global 说明
全局变量如果要在函数内部被赋值,则必须经过全局声明 global
默认全局变量在函数内部可以使用,但只能取值,不能赋值
不能先声明为局部变量,再用 global 声明为全局变量,此做法不符合语法规则
函数的形参已经时局部变量,不能用 global 声明为全局变量
错误示例
a = 100 b = 200 def fa(a): b = 20 # SyntaxError: name 'b' is assigned to before global declaration global b b = 222
lambda 表达式(又称匿名函数)
语法
lambda [函数的参数列表]: 表达式
作用
创建一个匿名函数对象
同 def 类似,但不提供函数名
说明
lambda 表达式 的创建函数只能包含一个表达式
示例
def myadd(x, y): return x + y print('1 + 2 =', myadd(1, 2)) # 3 # myadd 函数可以改写成 myadd2 = lambda x, y: x + y print('3 + 4 =', myadd2(3, 4)) # 7
示例2
>>> mymul = lambda a, b, c: a * b + c >>> >>> mymul(3, 4, 5) 17 >>> def mymul2(a, b, c): ... return a * b + c ... >>> mymul2(3, 4, 5) 17
id(x) 函数
作用
返回一个对象在内存中的地址
示例
>>> L = list(range(10)) >>> id(L) 140416266741832 >>> L2 = list(range(10)) >>> id(L2) 140416266741896 >>> L [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> L2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> L is L2 False
is / is not 运算符
is 作用
判断两个对象的id ,如果为同一个地址,返回True, 否则返回False
is not 返回值与 is 相反
示例
>>> weimingze = "小眀" >>> weilaoshi = weimingze # 两个变量同时绑定同一个字符串"魏明择" >>> >>> weilaoshi is weimingze # id(weilaoshi) == id(weimingze) 返回True True >>> laowei = "我是" + "小明" # 创建一个新的字符串"我是小明" >>> >>> weimingze is laowei # id(weiweimingze) == id(laowei) # 返回False False
None 对象
python 内部只有一个None 对象
通常判断一个变量是否绑定None,用 is 运算符(很少用 == 运算符)
函数式编程
用一系列函数来解决问题
求 1 + 2 + 3 + 4 + ..... 99 + 100 的和 # 用函数式编程 print(sum(range(1, 101)))
python 中的常用高阶函数
高阶函数是指,函数的参数可以传入函数
>>> def fb(a, b): ... print(a) ... print(b) ... print(b(a)) # b([1, 2, 3, 4]) # 等用于 sum([1, 2, 3, 4]) ... >>> fb([1, 2, 3, 4], sum) [1, 2, 3, 4] <built-in function sum> 10
python 中常用的函数
map 函数
filter 函数
sorted 函数
函数 说明 map(func, 可迭代对象1, ...) 返回一个可迭代对象, 此可迭代对象的每个数据用函数func 处理后返回 filter(func, 可迭代对象) 返回一个可迭代对象, 此可迭代对象的数据用func 函数进行筛选后过滤 sorted(可迭代对象, key=None,reverse=False) 返回一个列表, 所有的可迭代对象用key 的返回值进行排序
map函数
>>> def power2(x): ... return x ** 2 ... >>> L = [8, 5, 1, 3] # 求出 列表内 平方并打印 >>> for x in map(power2, L): # 把 power2 函数和 列表 L 交给 map 函数 ... print(x) ... 64 25 1 9
filter 函数
>>> def is_odd(x): ... return x % 2 == 1 ... >>> is_odd(3) True >>> is_odd(10) False >>> L = [8, 5, 2, 1, 8, 6, 9, 7] >>> # 把列表里所有的奇数取出来 >>> L2 = list(filter(is_odd, L)) >>> L2 [5, 1, 9, 7]
sorted 函数
>>> L = [5, -2, 4, -3, 1] >>> sorted(L) # 默认是升序排序 [-3, -2, 1, 4, 5] >>> sorted(L, reverse=True) # 降序排序 [5, 4, 1, -2, -3] >>> abs(-2) # abs 用来返回一个 数的绝对值 2 >>> abs(2) 2 >>> sorted(L, key=abs) # [1, -2, -3, 4, 5] # 用每个数据 abs 的返回值作为排序依据进行排序 [1, -2, -3, 4, 5]
模块
一个.py 文件就是一个模块
模块是含有一些列数据,函数,类等的程序
作用
把相关功能的函数等放在一起有利于管理,有利于多人合作开发
模块的分类
模块名如果要给别的程序导入,则模块名必须是 标识符
内置模块(在python3 程序内部,可以直接使用)
标准库模块(在python3 安装完后就可以使用的 )
第三方模块(需要下载安装后才能使用)
自定义模块(用户自己编写)
模块名如果要给别的程序导入,则模块名必须是 标识符
实例
# file: mymod.py ''' 小张写了一个模块,内部有两个函数,两个字符串 ... 此处省略 200字 ''' name1 = 'audi' name2 = 'tesla' def mysum(n): ''' 此函数用来求和 by weimingze ''' print("正在计算, 1 + 2 + 3 + .... + n的和 ") def get_name(): return "tarena"
调用模块
# file: test_mod.py # 小李写的程序,小李想调用 小张写的 mymod.py 里的两个函数和两个字符串 # 用import 语句导入模块 import mymod print(mymod.name1) # Audi print(mymod.name2) # tesla mymod.mysum(100) # 调用 mymod 模块里的 mysum 函数 print(mymod.get_name()) # 'tarena'
import 语句
导入
语法
import 模块名 [as 模块新名字1]
导入一个模块到当前程序
from 模块名 import 模块属性名 [as 属性新名]
导入一个模块内部的部分属性到当前程序
from 模块名 import *
导入一个模块内部的全部属性到当前程序
示例
import mymod mymod.mysum(10) # 要加模块名 from mymod import get_name print(get_name()) # 调用get_name 时不需要加 "模块名." from mymod import * print(get_name()) print(name2)
- 模块的内部属性
__file__ 绑定 模块的路径 __name__ 绑定模块的名称 如果是主模块(首先启动的模块)则绑定 '__main__' 如果不是主模块则 绑定 xxx.py 中的 xxx 这个模块名
python 的第三方模块
random 模块
生成随机数
文档位置: https://docs.python.org/zh-cn/3/library/random.html
>>> import random >>> random.randint(1, 6) # random.randint(a,b) 生产 a~b的随机整数 3 >>> random.randint(1, 6) 4 >>> random.random() # random.random 生成包含0 但不包含1 的浮点数 0.5884109388439075 >>> random.choice("ABCD") # 从一个序列中,随机返回一个元素 'C' >>> random.choice("ABCD") 'B' >>> L = [1, 2, 3, 6, 9] >>> random.choice(L) 6 >>> random.shuffle(L) # random.shuffer(x) # 把列表X 打乱 >>> L [1, 6, 2, 9, 3]
time 模块
时间戳:从 1970年1月1日 0:0:0 UTC 时间 开始计时到现在的秒数
UTC 时间 : 世界协调时间
struct_time 用 含有9个元素的元组来表示时间
>>> import time >>> time.time() # 返回当前时间的时间戳 1617117219.0382686 >>> time.ctime() #返回当前的UTC 时间的字符串 'Tue Mar 30 23:14:48 2021' >>> t1 = time.localtime() # 返回当前的本地时间元组 >>> t1 time.struct_time(tm_year=2021, tm_mon=3, tm_mday=30, tm_hour=23, tm_min=18, tm_sec=22, tm_wday=1, tm_yday=89, tm_isdst=0) >>> t1.tm_year 2021 >>> t1.tm_yday 89 >>> time.sleep(3) # time.sleep(n) # 让程序睡眠 n 秒 >>> time.strftime("%Y-%m-%d", t1) # 格式化时间 '2021-03-30' >>> time.strftime("%y-%m-%d", t1) '21-03-30' >>> time.strftime('%Y-%m-%d %H:%M:%S', t1) '2021-07-21 17:37:41' # 用时间元组来创建一个自定义的时间 >>> t2 = time.struct_time ( (2021,1, 1, 10, 11, 20, 0, 0, 0) )
datetime 模块
>>> import datetime >>> d1 = datetime.datetime.now() # 返回当前的时间 >>> d1 datetime.datetime(2021, 3, 30, 23, 32, 7, 342559) >>> d1.year 2021 >>> d1.year, d1.month, d1.day, d1.hour, d1.minute, d1.second, d1.microsecond # 用 datetime 的各个属性可以得到 具体的信息 (2021, 3, 30, 23, 32, 44, 757673) >>> d1.strftime("%Y-%m-%d") '2021-03-30' # 计算时间差 >>> delta_time = datetime.timedelta(days=2, hours=1) # 生成 2天1小时后的时间差 >>> delta_time datetime.timedelta(2, 3600) >>> t1 = datetime.datetime.now() # 得到当前时间 >>> t1 datetime.datetime(2021, 3, 30, 23, 39, 26, 863109) >>> t1 + delta_time # 计算 未来时间
异常
用作
信号通知,通知上层调用者有错误产生需要处理
try 语句
语法
try: 可能发生异常的语句块 except 错误类型1 [as 变量名1]: 异常处理语句块1 except 错误类型2 [as 变量名2]: 异常处理语句块2 ... except 错误类型n [as 变量名n]: 异常处理语句块n except: 异常处理语句块other else: 未发生异常的语句 finally: 最终的处理语句
作用
尝试捕获异常,得到异常通知,将程序由异常状态变为正常状态
说明
except 子句可以有 1个或多个
except: 不给错误类型,可以匹配全部的错误类型
else 子句里的语句会在 没有错误发生时执行,当处于异常时不执行
finally 子句里的语句,无论何时都执行
示例
try: x = int(input("请输入一个整数:")) print('x=', x) except ValueError: print('您的输入不能转成整数') print("程序结束")
raise 语句
问题
# 写一个函数, get_score 函数,读取用户输入的整数成绩, # 成绩的正常值是0~100 之间, 要求, 如果不在0~100 之间 # 报 ValueError类型的错误 def get_score(): x = int(input('请输入成绩:')) if 0 <= x <= 100: return x raise ValueError
语法
raise 异常类型 或 raise 异常对象
作用
抛出一个错误,让程序进入异常状态
发送错误通知给调用者
示例:
# 写一个函数, get_score 函数,读取用户输入的整数成绩, # 成绩的正常值是0~100 之间, 要求, 如果不在0~100 之间 # 报 ValueError类型的错误 def get_score(): x = int(input('请输入成绩:')) if 0 <= x <= 100: return x # raise ValueError raise ValueError('用户输入的成绩不在 0~100 之间') try: score = get_score() print(score) except ValueError as err: print("成绩输入有误 err=", err)
- 异常类型的可选种类
详见:
>>> help(__builtins__)
字节串 bytes 和字节数组 bytearray
1 一个字节(byte)是8个二进制的位 (bit)
1个byte的取值范围是 0 ~ 255
bytes 不可变
bytearray 可变
字节串的字面值
>>> b'' >>> b"" >>> b'''''' >>> b'''''' >>> b'ABC' >>> bytes([65, 66, 67, 68]) >>> bytes([65, 66, 67, 68, 200,255]) >>> bytes([65, 66, 67, 68, 200,255, 300]) # 300 超出了255 报错 >>> bytearray([65, 66, 67, 68, 200,255]) # 字节数组的创建必须使用bytearray函数
字节串的运算
字节串是序列,运算规则同元组一样
+ += * *= > >= < <= == != in / not in 索引和切片
示例
>>> b = bytes([65, 66, 67, 68, 200,255]) >>> b b'ABCD\xc8\xff' >>> b[0] 65 >>> b[:2] b'AB' >>> b += b'123' >>> b b'ABCD\xc8\xff123' >>> len(b) 9
bytes 和 str 的区别
bytes 存储的字节 (0~255 之间的数)
str 存储的是字符的编码
bytes 与 str 转换
编码(encode) str -------------> bytes b = s.encode(encoding='utf-8') 解码(decode) bytes -----------> str s = b.decode(encoding='utf-8')
示例
>>> s = 'hello 小张' >>> >>> b = s.encode() # 将字符串编码成为字节串 >>> b b'hello \xe5\xb0\x8f\xe5\xbc\xa0' # 在utf-8 编码中,1个汉字通常用3个字节进行编码 >>> len(b) 12 >>> s2 = b.decode() # 将字节串解码成为字符串 >>> s2 'hello 小张'
文件
什么是文件
文件通常用来存储以字节为单位的数据
文件的操作流程
打开文件
读/写文件
关闭文件
打开文件用open 函数
open(file, mode='rt') # open 函数返回文件流对象 # 打开失败回收到异常通知 # mode 的缺省值的 'rt'
myfile = open('/etc/passwd', 'rt') s = myfile.read() # 用 myfile 绑定的文件流对象的read() 方法,得到 文件内部的数据 print(s) myfile.close() # 关闭文件
示例
两种操作文件的模式
直接用 字节串操作文件(内部可以存储文字,也可以存储图片等信息)
打开模式 mode = 'b' # b是binary
用字符串操作文本文件(内部存储的都是文字)
打开模式 mode='t' # t 是text 的首字母(默认为't')
示例见
f = open('mynote.txt', 'rt') # 'r 代表读 s = f.read() # 在't' 模式下 ,read 返回字符串 print(s) f.close() # 关闭
f = open('mynote.txt', 'rb') # 'r' 代表读 'b' 代表以二进制方式操作 b = f.read() # 在't' 模式下 ,read 返回字节串 print(b) s = b.decode() # 将字节串转成了字符串 print(s) f.close() # 关闭
用字符串操作文件
用字节串操作文件
文件的打开模式 mode
模式
说明
't'
以文本(字符串) 的模式操作文件(默认)
'b'
以二进制(字节串) 的模式操作文件
文件的打开方式 mode
方式
说明
'r'
读取文件(默认)
'w'
写和覆盖写文件(如果文件不存在则创建文件 )
'a'
写并且追加文件内容(如果文件不存在则创建文件)
python 文件流对象的方法
方法名
说明
F.close()
关闭文件
读取文件的方法
F.read(size=-1)
读取文件(不给出size 参数过读取全部)
F.readline()
读取文件中的一行,以'\n' 作为行分隔符
F.readlines()
读取文件中的全部,以'\n' 作为行分隔符, 返回行的列表
写文件的方法
F.write(x)
写文件: 'b'模式 x 必须是字节串, 't'模式x必须是字符串, 如果文件不存在则新建文件
mynote.txt 文件中的内容
我是小眀
我在 tarena读数据
>>> f = open('mynote.txt', 'rb') >>> f.read() # 返回全部 b'\xe6\x88\x91\xe6\x98\xaf\xe9\xad\x8f\xe7\x9c\x80\xe6\x8b\xa9\n\xe6\x88\x91\xe5\x9c\xa8 tarena\n' >>> f.read() # 当到达文件尾部,返回空 b'' >>> f.close() >>> f = open('mynote.txt', 'r') >>> f.read() '我是小明\n我在 tarena\n' >>> f.close() >>> f = open('mynote.txt', 'r') >>> f.readline() # 返回一行 '我是小眀\n' >>> f.readline() '我在 tarena\n' >>> f.readline() '' >>> f.close() >>> f = open('mynote.txt', 'r') >>> f.readlines() # 取出所有的行数据,返回列表 ['我是小眀\n', '我在 tarena\n'] >>> f.close()
写数据
>>> f = open('python.log', 'w') # 以字符串方式写文件, 如果文件文件不存在回新建一个文件 >>> f.write('该吃饭了') 4 >>> f.write('!') 1 >>> f.write('\n') # 写一个换行 1 >>> f.write('下课') 2 >>> f.close()
移动文件的读写指针seek 方法
F.seek(偏移量, whence=相对位置)
偏移量(整数)
大于0 向文件末尾方向
小于0 向文件头方向
相对位置:
0 代表从文件头开始偏移
1 代表从当前的读写位置开始偏移
2 代表从文件末尾开始偏移
在读写二进制模式打开的文件,在不关闭文件的情况下, 可以使用seek 方法移动文件的读写指针
tell() 方法,返回文件的读写指针的位置
F.tell() # 返回整数
示例
mynote3.txt 的内容
1234567890ABCDE
示例程序
myfile = open('mynote2.txt', 'rb') print('刚打开文件时,文件指针的位置是:', myfile.tell()) # 0 b = myfile.read(2) print(b) # b'12' print('读取两个字节后,文件指针的位置是:', myfile.tell()) # 2 # 读取 67890 这个5个字节 # myfile.seek(5, 0) # 0 开始位置,向后移动5个字节 # myfile.seek(3, 1) # 1 当前位置,向后移动3个字节 myfile.seek(-10, 2) # 2 文件末尾位置,向前移动10个字节 print('myfile.seek()后,文件指针的位置是:', myfile.tell()) # 5 b = myfile.read(5) # b'67890' print('myfile.read(5)后,文件指针的位置是:', myfile.tell()) # 10 print(b) myfile.close()
with 语句
通过with 语句打开文件,with 语句结束,则文件会自动关闭
语法
with 表达式1 as 变量1[, 表达式2 as 变量2, ...]: 语句块
示例
# file: mynote2.txt # 不用with 语句 f = open('mynote2.txt') s = f.read() print(s) f.close() # 用with 语句 with open('mynote2.txt') as f: s = f.read() print(s)
sys模块
Shell 的位置参数
$0 $1 $2
#! /usr/bin/python3 # file 04_myprog.py import sys print(sys.argv) # ['./04_myprog', '/root', 'hello'] # 如下是shell 中运行的内容 $ chmod +x myprog.py $ ./myprog /root hello # $0='./04_myprog' $1='/root' $2='hello'
os 模块
python 上获取命令行参数
对操作系统的访问大多使用 python 中的os 模块
官方文档: os --- 多种操作系统接口 — Python 3.9.7 文档
>>> import os >>> os.getcwd() # 返回当前的工作路径,pwd '/root/桌面/py02/day03_code' >>> os.mkdir('/tmp/nsd21xx') # mkdir /tmp/nsd21xx >>> os.makedirs('/tmp/nsd21xx/a/b/c') # mkdir -p /tmp/nsd21xx/a/b/c >>> os.listdir() # ls ['mygames.py', '.idea', 'mynote.txt', 'python.log', 'mynote2.txt', '03_file_seek.py', '04_myprog.py', '05_cp.py', '01_read_text_file_by_string.py', '02_read_text_file_by_bytes.py'] >>> os.listdir('/tmp') # ls /tmp # 列出所有的文件夹 [ 'nsd21xx', 'dir1', 'dir2'] >>> os.chdir('/tmp/nsd21xx') # cd /tmp/nsd21xx >>> os.getcwd() # pwd '/tmp/nsd21xx' >>> os.symlink('/etc/passwd', '/tmp/abc') # ln -s /etc/passwd /tmp/abc >>> os.mknod('/tmp/myfile.txt') # touch /tmp/myfile.txt >>> os.chmod('/tmp/myfile.txt', 0o755) # chmod 755 /tmp/myfile.txt >>> os.rename('/tmp/myfile.txt', '/tmp/a.txt') # mv /tmp/myfile.txt /tmp/a.txt >>> os.rmdir('/tmp/dir2') # rmdir /tmp/dir2 >>> os.remove('/tmp/a.txt') # rm /tmp/a.txt
字符串用于去掉空白字符串的方法
空白字符是指
' ', '\n' '\r' '\t'
>>> s = ' \n \t hello world \n' >>> s.strip() # 去掉左右两侧的空白字符 'hello world' >>> s.lstrip() # 去掉左侧的空白字符 'hello world \n' >>> s.rstrip() # 去掉右侧的空白字符 ' \n \t hello world'
os.path 模块
用于路径的操作的模块
>>> import os >>> os.path.isabs('/root/abc.txt') # 判断是否为绝对路径 True >>> os.path.isdir('/tmp/nsd21xx') # 判断是否是文件夹 True >>> os.mknod('/tmp/b.txt') # touch /tmp/b.txt >>> os.path.isfile('/tmp/b.txt') # 判断是否是文件 True >>> os.path.islink('/tmp/abc') # 判断是否是软连接? True >>> os.path.ismount('/home') # 存在并且是挂载点 True >>> os.path.exists('/root') # 判断文件或文件夹是否存在 True >>> os.path.basename('/tmp/nsd21xx/hello.py') # 返回文件名 'hello.py' >>> os.path.dirname('/tmp/nsd21xx/hello.py') # 返回路径 '/tmp/nsd21xx' >>> os.path.split('/tmp/nsd21xx/hello.py') # 拆分 路径和文件名 ('/tmp/nsd21xx', 'hello.py') >>> os.path.join('/tmp/nsd21xx', 'world.py') # 拼接路径 '/tmp/nsd21xx/world.py'
os.walk() 函数
遍历文件夹 [root@localhost tmp]# tree /tmp/nsd21xx/ /tmp/nsd21xx/ ├── a │ ├── aaa.txt │ └── b │ ├── bbb.txt │ └── c └── aa └── bb └── cc
示例
>>> for x in os.walk('/tmp/nsd21xx'): ... print(x) ... # (路径 , 路径内的所有文件夹列表 , 路径内的所有文件列表) ('/tmp/nsd21xx', ['a', 'aa'], []) ('/tmp/nsd21xx/a', ['b'], ['aaa.txt']) ('/tmp/nsd21xx/a/b', ['c'], ['bbb.txt']) ('/tmp/nsd21xx/a/b/c', [], []) ('/tmp/nsd21xx/aa', ['bb'], []) ('/tmp/nsd21xx/aa/bb', ['cc'], []) ('/tmp/nsd21xx/aa/bb/cc', [], [])
shutil 模块
官方文档: shutil --- 高阶文件操作 — Python 3.9.7 文档
>>> import shutil >>> f1 = open('/etc/passwd', 'rb') >>> f2 = open('/tmp/mypass.txt', 'wb') >>> shutil.copyfileobj(f1, f2) >>> f1.close() >>> f2.close() >>> >>> shutil.copy('/etc/passwd', '/tmp/mypass2.txt') # cp /etc/passwd /tmp/mypass2.txt '/tmp/mypass2.txt' >>> shutil.copytree('/root/桌面/py02/day03_code', '/tmp/mycode') # cp -r /root/桌面/py02/day03_code /tmp/mycode '/tmp/mycode' >>> shutil.move('/tmp/mypass.txt', '/tmp/nsd21xx/a.txt') # mv /tmp/mypass.txt /tmp/nsd21xx/a.txt >>> shutil.rmtree('/tmp/mycode') # rm -rf /tmp/mycode >>> shutil.chown('/tmp/mypass.txt', user='xxx', group='yyy') # 改属主属组
生成器
生成器是在程序运行时生成数据,与容器不同,它通常不会在内存中保留大量的数据,而是现用现生成。
生成器可以用算法动态的生成数据
生成器有两种
生成器函数
生成器表达式
生成器函数
含有yield 语句的函数 是生成器函数,此函数调用回返回一个生成器对象,生成器也是可迭代对象
yield 语句的语法
yield 表达式
生成器函数示例:
# 定义一个生成器函数, 有 yield 的函数调用后回返回生成器对象 def myrange(stop): i = 0 while i < stop: yield i # 为 遍历次生产器的for 语句提供数据 i += 1 for x in myrange(5): print('x=', x)
生成器表达式
语法:
( 表达式 for 变量 in 可迭代对象 [if 真值表达式])
[] 内容代表可以省略
作用
用推导式的形式创建一个生成器
示例
>>> [x ** 2 for x in range(1, 5)] # 列表解析(列表推导式) [1, 4, 9, 16] >>> >>> (x ** 2 for x in range(1, 5)) # 生成器表达式 <generator object <genexpr> at 0x7f41dcd30a40> >>> for y in (x ** 2 for x in range(1, 5)): ... print(y) ... 1 4 9 16
生成器表达式
语法:
( 表达式 for 变量 in 可迭代对象 [if 真值表达式])
[] 内容代表可以省略
作用
用推导式的形式创建一个生成器
示例
>>> [x ** 2 for x in range(1, 5)] # 列表解析(列表推导式) [1, 4, 9, 16] >>> (x ** 2 for x in range(1, 5)) # 生成器表达式 <generator object <genexpr> at 0x7f41dcd30a40> >>> for y in (x ** 2 for x in range(1, 5)): ... print(y) ... 1 4 9 16
面向对象编程 Object-Oriented Programming(OOP)
程序 = 数据 + 算法(操作数据的方式可方法)
数据
数字
字符串
容器
算法
函数
模块
数据 + 函数 + 类
函数式编程, 数据和行为(函数) 是分开的
Person1 = { 'name': 'weimingze', 'age': 35 } Person2 = { 'name': 'xiaozhang', 'age': 18 } def update_age(person): person['age'] += 1 update_age(Person1) update_age(Person2)
对象
是指现实世界的物体
什么是面向对象
把一切看成对象(实例), 用各个对象的关系来描述事物
对象的特征
对象有很多属性(名词,形容词,...), 数据
姓名, 年龄,性别....
对象有很多行为(动作,动词), 方法(属于某个对象的函数)
学习,吃饭, 踢球,工作
类
拥有相同属性和行为的对象分为一组,即为一个类
/-------> BYD E6(京A.88888) 实例(也叫对象)
车(类)
\-------> BWM X5(京B.66666) 实例(也叫对象)
/-------> 100 (对象)
int(类)
\-------> 200 (对象)
/---> True
bool(类)
\---> Falseint float dict list tuple
class 语句
语法
class 类名 (继承列表): 语句
作用
创建一个类
类用于描述对象的行为和属性
类可以创建一个或多个对象
示例
class Car: pass
构造函数
调用表达式
类名(实参)
作用
创建这个类的实例对象
示例
car1 = Car() # 创建 第一个Car 类型的对象 car2 = Car() # 创建 另一个Car 类型的对象 # L1 = list() 创建 第一个 list 类型的列表 L2 = list() 创建 另一个 list 类型的列表
实例属性
每个对象可以有自己的变量,称之为实例属性
属性的使用语法
实例.属性名
遵循变量的赋值规则
示例
car1.color = '红色' # 颜色 为 car1 创建属性 color 绑定 '红色' car1.brand = '比亚迪' # brand 品牌 car1.plate = '京A.88888' # 牌照 car2.color = '白色' car2.brand = '宝马' car2.plate = '京B.66666'
删除属性用 del 语句
# 如 del car1.color
实例方法(instance method)
定义的语法
class 类名[继承列表]: def 实例方法名(self, 形参名1, 形参名2, 形参名3, ....): 语句块
作用
用于描述一个对象的行为,让此类型的全部对象都有相同的行为
说明
实例方法的实质是一个函数,他是定义在类内的函数
实例方法至少有一个形参,第一个形参绑定调用这个方法的实例,一般命名为 self
调用语法
实例.实例方法名(实参列表)
# 或
类名.实例方法名(实例,实参列表)示例
# 类的定义 class Car: # 实例object方法 def run(self, km): print(self.color, '的', self.brand, self.plate, '正在以', km, '公里/小时的速度行使') .... 此处省略了创建对象的和添加属性的代码 # 调用方法 car1.run(110) car2.run(180) # 方法2 # Car.run(car1, 120) # Car.run(car2, 160)
初始化方法(也叫构造器方法)
作用
对新创建的对象添加属性
语法格式
class 类名: def __init__(self [,形参列表]): 语句块
说明
初始化方法名 必须为
__init__
初始化方法会在类创建实例时自动调用,且将实例对象通过第一个参数传入
__init__
方法构造函数的实参将通过
__init__
的参数列表传入到__init__
方法中初始化方法内如果需要用return 语句返回,则必须返回None
练习
# 写一个小狗类 class Dog: def __init__(self, ...): pass dog1 = Dog('白色', '藏獒') dog1.eat(1, '羊肉') # 白色 的 藏獒 吃了 1 斤 羊肉, dog2 = Dog('灰色', '导盲犬') dog2.eat(2, '狗粮') # 灰色 的 导盲犬 吃了 2 斤 狗粮, dog1.eat(2, '牛肉') # 白色 的 藏獒 吃了 2 斤 牛肉, dog1.info() # 白色 的 藏獒 吃过 ['羊肉', '牛肉'] dog2.info() # 灰色 的 导盲犬 吃过 ['狗粮']
答案
# 写一个小狗类 class Dog: def __init__(self, color, kind): self.color = color self.kind = kind self.foods = [] # 用来记录吃过的食物 def eat(self, weight, food): print(self.color, '的', self.kind, '吃了', weight, '斤', food) self.foods.append(food) # 追加到 foods 列表里 def info(self): print(self.color, '的', self.kind, '吃过', self.foods) dog1 = Dog('白色', '藏獒') dog1.eat(1, '羊肉') # 白色 的 藏獒 吃了 1 斤 羊肉, dog2 = Dog('灰色', '导盲犬') dog2.eat(2, '狗粮') # 灰色 的 导盲犬 吃了 2 斤 狗粮, dog1.eat(2, '牛肉') # 白色 的 藏獒 吃了 2 斤 牛肉, dog1.info() # 白色 的 藏獒 吃过 ['羊肉', '牛肉'] dog2.info() # 灰色 的 导盲犬 吃过 ['狗粮']
继承(inheritance)和派生(derived)
继承是从已经有的类中派生出新类,新类具有父类的属性和行为,并能扩展新的能力
派生是从已经有的类中衍生出新类,在新类的基础上可以添加属性和行为
作用
用继承派生机制,可以将一些共有的功能加在基类(也叫父类)中,实现代码共享
在不改变基类代码的基础上,改变原有的功能。
语法
class 类名(基类名): 语句块
示例1
# 继承的示例 # Human 类派生出 Student 类 class Human: # 定义一个人类 def say(self, what): '说' print("说:", what) def walk(self, distance): '走路' print('走了', distance, '公里') class Student(Human): # 定义一个学生了 def study(self, subject): print('学习', subject) class Teacher(Human): def teach(self, language): print('教', language) h1 = Human() h1.say('天气真好') h1.walk(5) s1 = Student() s1.walk(4) s1.say('有点累') s1.study('面向对象') t1 = Teacher() t1.teach('Python') t1.say('今天周四') t1.walk(6)
显式调用基类的初始化方法 super 函数
super() # 返回父类对象
覆盖
覆盖是指在有继承关系的类中,子类中实现了与父类中同名的方法,在子类实例调用该方法时,实际调用的是子类中的覆盖版本,这种现象叫覆盖
组合
class MyList: def __init__(self): self.data = [] def append(self, n): self.data.append(n) def insert_head(self, n): self.data.insert(0, n) L1 = MyList() # MyList 类型的对象中包含一个 list 类型的对象,这种叫组合 L1.append(100) L1.insert_head(0)
继承
class MyList(list): def insert_head(self, n): self.insert(0, n) L1 = MyList() # MyList 类型的对象中包含一个 list 类型的对象,这种叫组合 L1.append(100) L1.insert_head(0) print(L1)
多继承
多继承是指一个子类由两个或两个以上的父类(基类)
语法
class 类名(基类1,基类2, ...): 语句块
示例
class Plane: def fly(self, height): print("飞机以海拔", height,'米的高度飞行') class Car: def run(self, speed): print("汽车以", speed, '公里/小时的速度行驶') class PlaneCar(Plane, Car): pass pc = PlaneCar() pc.run(120) pc.fly(10000)
多继承可能会带来程序运行的不确定性,谨慎使用
>>> class A: ... def m(self): ... print('A') ... >>> class B: ... def m(self): ... print("B") ... >>> class C(A, B): ... pass ... >>> c = C() >>> c.m() A >>> class D(B, A): ... pass ... >>> d = D() >>> d.m() B
常用魔法方法, 在类定义中,很多以 双下划线开头和结尾的方法被称为魔法方法,是python 定义特殊功能的方法,
用dir函数可以查看对象的全部方法
>>> dir(list) ...
三个魔法方法
class Book:
def __init__(self, title, author):
'''初始化方法,在实例化时自动调用'''
self.title = title # 标题
self.author = author # 作者
def __str__(self):
'''将对象转成字符的时候会调用'''
return "《%s》" % self.title
def __call__(self):
'''将实例当成函数来调用,执行此函数内的代码'''
print('《%s》是%s 编著的' %(self.title, self.author) )
if __name__ == '__main__':
b1 = Book('Linux 运维之道', '丁明一')
print(b1)
b1()
正则表达式 (regular express)
正则表达式是表示 文字的排列规则的一个字符串, 使用来匹配文字的匹配模式.
作用
用于文字的定位,搜索和内容的提取
元字符
类别
元字符
匹配字符
.
[...]
[^...]
\d \D \w \W \s \S匹配重复
*
+
?
{n}
{m,n}
匹配位置
^ $ \b \B
其他
|
()
\
示例
# 标识符 的正则表达式 [A-Za-z_][A-Za-z_0-9]* # a* -> '' 'a' 'aaaaa' a+ -> 'a' 'aaaaaa' [ab]+ --> 'a' 'b' 'abaaabbb' [ab]{3} --> 'aaa' 'bbb' 'aba' [ab]{3,5}--> 'aaa' 'aaaaa' 'aabb' # 匹配 .mp3 文件 '\w\.mp3$'---> 'abc.mp3' '(\w\.mp3$)|(\w\.MP3$)' 'abc.mp3' 'abc.MP3' '\w\.[mM][pP]3$' 'abc.mP3' 'abc.mp3' 'abc.MP3'
普通字符
'ab' # 普通字符 只匹配'ab' >>> import re # 导入正则表表达式模块 >>> s = 'abcdeabca' >>> re.findall('ab', s) ['ab', 'ab']
或关系
| 匹配两侧任意的正则表达式 >>> import re # 导入正则表表达式模块 >>> s = 'abcdeabca' >>> re.findall('ab|de', s) ['ab', 'de', 'ab']
匹配单个字符串
. 匹配除换行符 以外的任意的一个字符 >>> import re >>> re.findall('张.丰', '张三丰,张四丰,张老师') ['张三丰','张四丰']
匹配字符集
[字符集] 匹配其中的一个字符 >>> import re >>> s = 'How are you!' >>> re.findall('[aeiou]', s) ['o', 'a', 'e', 'o', 'u'] >>> re.findall('[0-9A-Za-z]', 'A$%^^%b!#$@!#$0') ['A', 'b','0'] ^ 匹配目标字符的开始位置 $ 匹配目标字符的结束位置 >>> re.findall('^hello', 'hello world') ['hello'] >>> re.findall('^hello', 'a hello world') [] >>> re.findall('world$', 'hello world') ['world'] * 匹配前面的字符出现 0 或多次 + 匹配前面的字符出现 1 或多次 ? 匹配前面的字符出现 0 或1次 >>> re.findall('wo*', 'wooooooo~~w! woo') ['wooooooo', 'woo'] >>> re.findall('[A-Z][a-z]+', 'Hello World abcd') ['Hello','World'] >>> re.findall('-?[0-9]+', 'name: Jame, age: 18, money:-100') ['18', '-100'] {n} # 前面的字符出现n 次 {m,n} # 前面的字符出现m到n次 >>> re.findall('[0-9]{3}', '888 9999 1000000') ['888', '999', '100', '000'] >>> re.findall('[0-9]{4,10}', '888 9999 1000000') ['9999', '1000000'] \d 匹配任意的数字 [0-9] \D 匹配任意的非数字 >>> re.findall('\d{1,5}', 'MySql: 3306, http:80') ['3306', '80'] \w 匹配普通字符 \W 匹配非普通字符 普通字符是指 数字,字母,下划线,汉字 >>> re.findall('\w+', 'MySql: 3306, http:80') ['MySql', '3306', 'http', '80'] \s 匹配空字符 \S 匹配非空字符 空字符是指 '\r' '\n' '\t' '\v' '\f' >>> re.findall('\w+\s+\w+', 'hello world') ['hello world'] \b 表示单词的边界 \B 表示非单词的边界 >>> re.findall(r'\bis\b', 'This is a test') ['is'] >>> s = '''SERVER = 192.168.9.102 PORT = 80 SERVERNAME = GAME1 REMOTE = 188.3.69.888 ''' >>> server_re = r'SERVER\s*=\s*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' server_ip = re.findall(server_re, s) >>> server_re = r'SERVER\s*=\s*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' >>> server_ip = re.findall(server_re, s) >>> server_ip ['SERVER = 192.168.9.102'] >>> ip_list = re.findall(r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}', server_ip[0]) >>> print("SERVER=", ip_list[0])
模块内的
__name__
属性如果 一个模块是主模块,则
__name__
绑定'__main__'
如果 一个模块不是主模块,则
__name__
绑定文件名super() 函数
作用
显示的调用被覆盖的父类方法
示例
class A: def say_hello(self): print('Hello A') class B(A): def say_hello(self): print("hello B") # self.say_hello() 无限递归调用 # 能否在此方法内调用 A类里面的 say_hello() # 方法1 # A.say_hello(self) # 方法2 ,super() 会把self 看成是A类的对象 super().say_hello() b = B() b.say_hello() # hello B Hello A
多线程编程
一个进程可以有多个执行路径,通常可以每个执行路径分配在不同的CPU 上并行执行, 这种运行方式是多线程
文档:threading --- 基于线程的并行 — Python 3.9.7 文档
问题
如何能让下面的两个函数同时执行
import time def say_hello(): for x in range(10): print("hello!!!") time.sleep(1) def say_world(): for y in range(10): print('world!!!') time.sleep(1) say_hello() say_world()
使用多线程
创建线程对象的方法
import threading # 用threading 的 Thread 类来创建一个线程对象 threading.Thread(target=None, args=(), kwargs={}, *, daemon=None) 示例 import threading import time def say_hello(): for x in range(10): print("hello!!!") time.sleep(1) # 用threading 的 Thread 类来创建一个线程对象 用 t 变量绑定 t = threading.Thread(target=say_hello)
启动线程
用 Thread对象的start() 方法来启动线程,让 线程中 target 绑定的函数,异步执行
t.start()
完整示例
import threading # 导入多线程模块 import time def say_hello(): for x in range(10): print("hello!!!") time.sleep(1) def say_world(): for y in range(10): print('world!!!') time.sleep(1) if __name__ == '__main__': # 用多线程来并行 # 1. 创建一个线程,绑定 say_hello 函数 t1 = threading.Thread(target=say_hello) t1.start() # 启动 t1 线程 t2 = threading.Thread(target=say_world) t2.start() print("主线程运行结束") # 串行 # say_hello() # say_world()
json
json 全称( Javascript Object Notation) , 是一种轻量级的数据交互格式
json 是基于 Javascript 编程语言的格式
JSON 采用完全独立于编程语言的文本格式
标准JSON的合法符号:
{}(大括号)
"(双引号)
:(冒号)
,(逗号)
[ ](中括号)
Json 的数据类型
对象 object {}
数组 array []
字符串 string ""
数值 number (整数和浮点数)
布尔值 bool (true/false)
空值: null
字典中的两个人
[ { 'name': 'weimingze', 'age': 35 }, { 'name': '小王', 'age': 18, 'score': [90, 100, 85] }, ]
JSON中的两个人
[ { "name": "weimingze", "age": 35 }, { "name": "小王", "age": 18, "score": [90, 100, 85] }, ]
json 和 Python 的类型和值
Python Json dict {}object(对象) list, tuple []array数组 str "" string 字符串 int, float number 数字 True/False true/false None null
json 模块
内建模块
import json
json模块的四个常用函数
函数 说明 json.dump(obj, fw) 把python 对象编码为json 字符串并写入文件fw中 json.dumps(obj) 把python 对象编码为json 字符串并返回 json.load(fr) 从文件流对象fr中读取json数据解码后返回python对象 json.loads(json) 从json 字符串中解码Python 对象
示例见:
>>> infos = [ { 'name': 'weimingze', 'age': 35, 'gender': True, 'score': None }, { 'name': '小王', 'age': 18, 'score': [90, 100, 85] }, ] >>> infos [{'name': 'weimingze', 'age': 35, 'gender': True, 'score': None}, {'name': '小王', 'age': 18, 'score': [90, 100, 85]}] >>> >>> import json >>> s = json.dumps(infos) # 将infos 绑定的对象转为json 的字符串 >>> s '[{"name": "weimingze", "age": 35, "gender": true, "score": null}, {"name": "\\u5c0f\\u738b", "age": 18, "score": [90, 100, 85]}]' >>> objs = json.loads(s) # 将 json 的字符串,转为 python 的对象 >>> objs [{'name': 'weimingze', 'age': 35, 'gender': True, 'score': None}, {'name': '小王', 'age': 18, 'score': [90, 100, 85]}] >>> type(objs) <class 'list'>
API
Application Programming Interface 应用程序接口。在Web中,API 通常指HTTP协议的接口
示例
中国天气网查询天气情况的 API: http://www.weather.com.cn/data/sk/城市代码.html
城市代码:
http://www.weather.com.cn/data/sk/101010100.html # 城市代码码表 https://blog.csdn.net/wangqjpp/article/details/39957091
requests 模块
作用
发送HTTP 协议的请求,得到服务器响应的数据
模拟浏览器的行为
安装方法:
pip3 install requests
HTTP 协议的请求方式:
GET 请求
相当于查看 ,get请求可以获取网站的数据,请求参数通常跟在URL 的后面
POST请求
原意是创建或者添加, post请求通常用于提交表单或上传文件等
https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=baidu&wd=%E9%AA%B0%E5%AD%90&fenlei=256&rsv_pq=854e3d6f00038104&rsv_t=920aUYsotvE%2BTTV%2B4%2Fpf%2Fv1geYxMZTZFzMYCH5Fw%2Bg%2FZaWsk5SmRve30MRQ&rqlang=cn&rsv_enter=1&rsv_dl=ih_2&rsv_sug3=1&rsv_sug1=1&rsv_sug7=001&rsv_sug2=1&rsv_btype=i&rsp=2&rsv_sug9=es_2_1&inputT=7546&rsv_sug4=8033&rsv_sug=9
示例
使用request模块获取网页数据
>>> import requests # 向 https://www.baidu.com/s?wd=weimingze 发送GET请求得到响应 >>> r = requests.get('https://www.baidu.com/s?wd=weimingze') >>> r.text # 得到响应内容的文本信息 '<html>\r\n<head>\r\n\t<script>\r\n\t\tlocation.replace(location.href.replace("https://","http://"));\r\n\t</script>\r\n</head>\r\n<body>\r\n\t<noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>\r\n</body>\r\n</html>' >>> r = requests.get('http://photo.qc188.com/upload/20197/31/24820/l_1_20190731145347532.jpg') >>> r.content # 响应的字节串
使用request模块下载文件
>>> import requests >>> r = requests.get('http://photo.qc188.com/upload/20197/31/24820/l_1_20190731145347532.jpg') >>> r.content # 响应的字节串 # 下载图片 >>> r = requests.get('http://photo.qc188.com/upload/20197/31/24820/l_1_20190731145347532.jpg') >>> >>> with open('benz.jpg', 'wb') as fw: ... fw.write(r.content) # 将 响应的内容(bytes) 写入文件 ... 155157
用request模块获取 中国天气网的json 数据
>>> import requests >>> url = 'http://www.weather.com.cn/data/sk/101010100.html' >>> r = requests.get(url) >>> r.content # 返回字节串 b'{"weatherinfo":{"city":"\xe5\x8c\x97\xe4\xba\xac","cityid":"101010100","temp":"27.9","WD":"\xe5\x8d\x97\xe9\xa3\x8e","WS":"\xe5\xb0\x8f\xe4\xba\x8e3\xe7\xba\xa7","SD":"28%","AP":"1002hPa","njd":"\xe6\x9a\x82\xe6\x97\xa0\xe5\xae\x9e\xe5\x86\xb5","WSE":"<3","time":"17:55","sm":"2.1","isRadar":"1","Radar":"JC_RADAR_AZ9010_JB"}}' >>> r.json() # 将字节串,转化为python 的对象,相当于 json.loads(r.content.decode()) {'weatherinfo': {'city': 'å\x8c\x97京', 'cityid': '101010100', 'temp': '27.9', 'WD': 'å\x8d\x97é£\x8e', 'WS': 'å°\x8fäº\x8e3级', 'SD': '28%', 'AP': '1002hPa', 'njd': 'æ\x9a\x82æ\x97\xa0å®\x9eå\x86µ', 'WSE': '<3', 'time': '17:55', 'sm': '2.1', 'isRadar': '1', 'Radar': 'JC_RADAR_AZ9010_JB'}} >>> r.encoding # 查看当前的字符编码 'ISO-8859-1' >>> r.encoding = 'utf8' # 将编码改为 UTF-8 >>> r.json() {'weatherinfo': {'city': '北京', 'cityid': '101010100', 'temp': '27.9', 'WD': '南风', 'WS': '小于3级', 'SD': '28%', 'AP': '1002hPa', 'njd': '暂无实况', 'WSE': '<3', 'time': '17:55', 'sm': '2.1', 'isRadar': '1', 'Radar': 'JC_RADAR_AZ9010_JB'}}
requests.get ()为连接添加查询字符串使用params 字典完成
i
mport requests url = 'https://www.sogou.com/web' # https://www.sogou.com/web?query=linux s = input('请输入查询的内容:') params = {'query': s} r = requests.get(url, params=params) # 发出get请求,传入 ?query=s 查询字符串 # 相当于请求:https://www.sogou.com/web?query=linux with open('sogou_' + s + '.html', 'wb') as fw: fw.write(r.content) # 把 r.content 字节串写入文件 # https://www.sogou.com/web?query=linux s = input('请输入查询的内容:') params = {'query': s} r = requests.get(url, params=params) # 发出get请求,传入 ?query=s 查询字符串 # 相当于请求:https://www.sogou.com/web?query=linux with open('sogou_' + s + '.html', 'wb') as fw: fw.write(r.content) # 把 r.content 字节串写入文件
request 可以通过 headers 传递请求头
url = 'https://www.sogou.com/web' params = {'query': 'linux'} headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36' } # 带上 'User-Agent' 请求头,把自己伪装成浏览者 r = requests.get(url, params=params, headers=headers) r.text # 返回网页的内容
完整代码:
import requests url = 'https://www.sogou.com/web' # https://www.sogou.com/web?query=linux s = input('请输入查询的内容:') params = {'query': s} headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36' } # 带上 'User-Agent' 请求头,把自己伪装成浏览者 r = requests.get(url, params=params, headers=headers) # 发出get请求,传入 ?query=s 查询字符串 # 相当于请求:https://www.sogou.com/web?query=linux with open('sogou_' + s + '.html', 'wb') as fw: fw.write(r.content) # 把 r.content 字节串写入文件