面试前的临阵磨枪python
一、python
数据类型
字符串str:(不可变类型内部创建之后,可以取值 不可修改)
方法(用法就是字符串调用)
startswith() 判断字符串是否以 XX 开头?得到一个布尔值
v1 = "叨逼叨的一天,烦死了"
result = v1.startswith("叨逼叨的一天")
endswith() 判断字符串是否以 XX 结尾?得到一个布尔值
isdecimal() 判断字符串是否为十进制数?得到一个布尔值
v1 = "1238871" result = v1.isdecimal()
strip() 去除字符串两边的 空格、换行符、制表符,得到一个新字符串
msg = " H e ll o啊,树哥 " data = msg.strip()
split() 字符串切割,得到一个列表
data = "武沛齐|root|wupeiqi@qq.com"
result = data.split('|')
format() 格式化字符串,得到新的字符串
name = "{0}的喜欢干很多行业,例如有:{1}、{2} 等"
data = name.format("老王","护士","嫩模")
join() 字符串拼接,得到一个新的字符串
data_list = ["alex","是","大烧饼"] v1 = "_".join(data_list) # alex_是_大烧饼
replace() 字符串内容替换,得到一个新的字符串,原变量还是不变
data = "你是个好人,但是好人不合适我"
value = data.replace("好人","贱人")
lower()/upper() 字符串变小写/大写,得到一个新字符串
msg = "My Name Is Oliver Queen" data = msg.lower()
zfill() 帮助你填充0
data = "alex" v1 = data.zfill(10) print(v1) # 000000alex
列表list:(可变类型有序可修改)
方法(内部修改)
append 追加,在原列表中尾部追加值
data_list = []
v1 = input("请输入姓名")
data_list.append(v1)
extend 批量追加,将一个列表中的元素逐一添加另外一个列表
tools = ["搬砖","菜刀","榔头"] tools.extend( [11,22,33] ) #列表中的值逐一追加到tools中 print(tools) # ["搬砖","菜刀","榔头",11,22,33]
insert 插入,在原列表的指定索引位置插入值
user_list = ["苍老师","有坂深雪","大桥未久"] user_list.insert(0,"马蓉")
remove 在原列表中根据值删除(从左到右找到第一个删除)【慎用,里面没有会报错】
user_list = ["王宝强","陈羽凡","Alex","贾乃亮","Alex"]
user_list.remove("Alex")
pop 在原列表中根据索引踢出某个元素(根据索引位置删除)
user_list = ["王宝强","陈羽凡","Alex","贾乃亮","Alex"] user_list.pop(1) # ["王宝强","Alex","贾乃亮","Alex"]
clear 清空原列表
index 根据值获取索引
user_list = ["王宝强","陈羽凡","Alex","贾乃亮","Alex"]
index = user_list.index("Alex") # 2
sort 列表元素排序
reverse 反转原列表
字典:(字典是无序对象的集合,同一个字典中键名不能重复,键值则可以相同)
get() 获取值
info = {
"age":12,
"name":"武沛齐",
}
data1 = info.get("name")
keys() 获取所有的键
values() 获取所有的值
items() 获取所有的键值
update() 更新字典键值对
info = {"age":12, "status":True}
info.update( {"age":14,"name":"武沛齐"} ) # info中没有的键直接添加;有的键则更新值
setdefault() 设置值
data = {
"name": "武沛齐",
"email": 'xxx@live.com'
}
data.setdefault("age", 18)
print(data) # {'name': '武沛齐', 'email': 'xxx@live.com', 'age': 18}
pop() 移除指定键值对
info = {"age":12, "status":True,"name":"武沛齐"}
data = info.pop("age")
popitem() 按照顺序移除(后进先出)
py3.6后,popitem移除最后的值
py3.6之前,popitem随机删除
info = {"age":12, "status":True,"name":"武沛齐"}
data = info.popitem() # ("name","武沛齐" )
print(info) # {"age":12, "status":True}
print(data) # ("name","武沛齐")
元组tuple:(是不可更改顺序和元素的序列)
集合set:(集合是一个无序且包含不重复元素的数据类型)
add 添加元素
data = {"刘嘉玲", '关之琳', "王祖贤"}
data.add("郑裕玲")
discard 删除元素
data = {"刘嘉玲", '关之琳', "王祖贤","张曼⽟", "李若彤"}
data.discard("关之琳")
intersection 交集
s1 = {"刘能", "赵四", "⽪⻓⼭"}
s2 = {"刘科⻓", "冯乡⻓", "⽪⻓⼭"}
s4 = s1.intersection(s2) # 取两个集合的交集
print(s4) # {"⽪⻓⼭"}
union 并集
s1 = {"刘能", "赵四", "⽪⻓⼭"}
s2 = {"刘科⻓", "冯乡⻓", "⽪⻓⼭"}
s4 = s1.union(s2)
difference 差集
s1 = {"刘能", "赵四", "⽪⻓⼭"}
s2 = {"刘科⻓", "冯乡⻓", "⽪⻓⼭"}
s4 = s1.difference(s2)
文件操作
with上下文管理,它可以自动实现关闭文件
with open("xxxx.txt", mode='rb') as file_object:
data = file_object.read()
print(data)
read,读所有
readline,读一行
readlines,读所有行,每行作为列表的一个元素
内置函数
type,获取数据类型
range()
zip()将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象
一般zip()函数用于我们想同时处理两个列表里的数据
sorted()排序
isinstance() 判断对象是否是某个类或其子类的实例。
super() 按照mro继承关系向上找成员。
闭包 装饰器 迭代器 生成器
闭包:
学习闭包我们要清楚函数作用域、内存回收机制、作用域继承
作用域:
我们可以认为它是一个封闭的盒子,只让它在这个盒子里面进行操作。一个函数要执行时就会在内存里面创建一个独立作用域
比如在函数中一个变量,只能在函数这个独立作用域中使用(也就是封闭的盒子)。只要跳出这个作用域,就找不到该变量了。
而且函数执行完毕之后,这个独立作用域或(封闭的盒子)就会删除。有一种情况下这个封闭的盒子是不会删除的,那就是“闭包”
内存回收机制:
就是在用不到的内存空间,系统会自动进行清理出空间提供给其他程序使用。
内部函数引用外部的函数的变量,外部函数执行完毕,作用域也不会删除。从而形成了一种不删除的独立作用域。
某一个变量或者对象被引用,因此在回收的时候不会释放它,因为被引用代表着被使用,回收机制不会对正在引用的变量或对象进行回收的。
作用域继承:
比如我这里有一个大的盒子作为一个父级的作用域,然后在这个大的盒子里边放一个小的盒子,作为子作用域。我们规定可以在小盒子中获取到大盒子中的东西,大盒子不能获取小盒子里的东西就称为作用域继承
在一个函数里边我们再声明一个函数,内部函数可以访问外部函数作用域的变量,而外部的函数不能获取到内部函数的作用域变量。
什么是闭包:
那就是在一个函数里边再定义一个函数。这个内部函数一直保持有对外部函数中作用域的访问
函数执行,形成一个独立作用域,保护里边的私有变量不受外界的干扰,除了保护私有变量外,还可以存储一些内容,这样的模式叫做闭包。
def demo_outer(x): def demo_inner(y): print("x的值:{}, y的值:{}, x + y 的值:{}".format(x, y, x + y)) return demo_inner do = demo_outer(12) # 返回内部函数demo_inner do(34) # 执行内部函数
x的值:12, y的值:34, x + y 的值:46
装饰器:
装饰器本质上就是一个闭包函数,它只是一个传递函数对象的闭包函数(闭包传递的参数是变量)
functools在装饰器中使用,保留原函数的属性,加上wraps
import functools def auth(func): @functools.wraps(func) def inner(*args, **kwargs): """巴巴里吧""" res = func(*args, **kwargs) # 执行原函数 return res return inner
迭代器:
官方说法:
具有 __iter__() 和 __next__() 两个方法的是迭代器
具有 __iter__() 可迭代对象
理解说法:
迭代器: 迭代数据的 工具
可迭代对象:可以迭代的 数据
可迭代对象 =>(转变) 迭代器 (可迭代对象到迭代器的过程)
把不能够直接通过next获取的数据 =>(转变) 可以直接被next获取数据
生成器:
本质就是迭代器,可以自定义迭代的逻辑
创建方式两种
(1) 生成器表达式(推导式) a = (i for i in range(10)) # 返回的是生成器对象
(2) 生成器函数 (含有yield 关键字)
内置模块
sys模块 主要是用于提供对python解释器相关的操作
# 导入模块路径 print(sys.path)
OS模块 是Python标准库中的一个用于访问操作系统功能的模块,使用OS模块中提供的接口,可以实现跨平台访问
# 1. 获取当前脚本绝对路径
abs_path = os.path.abspath(__file__)
# 2. 获取当前文件的上级目录
base_path = os.path.dirname( os.path.dirname(路径) )
# 3. 路径拼接
p1 = os.path.join(base_path, 'xx')
p2 = os.path.join(base_path, 'xx', 'oo', 'a1.png')
# 4. 判断路径是否存在
exists = os.path.exists(p1)
# 5. 创建文件夹
os.makedirs(路径)
# 7. 删除文件或文件夹
os.remove("文件路径")
random模块
# 获取范围内的随机整数 v = random.randint(10, 20)
json模块,是python内部的一个模块,可以将python的数据格式 转换为json格式的数据(本质就是字符串常用于网络数据传输),也可以将json格式的数据转换为python的数据格式。
-
json.dumps,序列化生成一个json字符串。 -
json.loads,反序列化生成python数据类型。
time模块
# 获取当前时间戳(自1970-1-1 00:00) v1 = time.time()
# 时区 v2 = time.timezone # 停止n秒,再执行后续的代码。 time.sleep(5)
datetime模块
v1 = datetime.now() # 当前本地时间
# 字符串格式的时间 ---> 转换为datetime格式时间 text = "2021-11-11" v1 = datetime.strptime(text,'%Y-%m-%d') # %Y 年,%m,月份,%d,天。
# 时间戳格式 --> 转换为datetime格式 ctime = time.time() # 11213245345.123 v1 = datetime.fromtimestamp(ctime)re模块,可以处理正则表达式并对文本进行处理。
findall,获取匹配到的所有数据
match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None
search,浏览整个字符串去匹配第一个,未匹配成功返回None
sub,替换匹配成功的位置
面向对象
方法
用哪种方法是看参数是否需要,用哪种参数就用哪种方法
绑定方法
默认有一个self参数,由对象进行调用(此时self就等于调用方法的这个对象)【对象&类均可调用】
类方法
@classmethod 默认有一个cls参数,用类或对象都可以调用(此时cls就等于调用方法的这个类)【对象&类均可调用】
静态方法
@staticmethod 无默认参数,用类和对象都可以调用。【对象&类均可调用】
在类中 @classmethod 和 @staticmethod 的作用?
一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。
而使用 @staticmethod或@classmethod,就可以不需要实例化,
直接: 类名.方法名() 来调用。
既然@staticmethod和@classmethod都可以直接 类名.方法名() 来调用,那有什么区别呢
@staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用 函数 一样。
如果在@staticmethod中要调用到这个类的一些属性方法,只能直接 类名.属性名 或 类名.方法名。
@classmethod 是一个函数修饰符,它表示接下来的是一个 类方法 类方法的第一个参数cls
类方法有类变量cls传入,从而可以用cls做一些相关的处理。并且有子类继承时,调用该类方法时,传入的类变量cls是子类,而非父类。
而@classmethod因为持有cls参数,可以来调用 类的属性,类的方法,实例化对象 等,避免硬编码。
普通对象方法至少需要一个self参数,代表类对象实例
特殊成员
__init__
初始化方法 用于在对象中初始化值。
__new__
构造方法
用于创建对象 (__new__方法是在实例对象创建时执行的(第一步先创建 空对象 并返回),
而构造方法__init__是实例创建后执行的(第二部初始化对象,在空对象中创建数据))
--单例模式会用,平时我们不写 默认继承object类的new方法
__call__
对象()时,会自动执行call方法
`__str__`
(里面必须返回字符串 有助于测试 )没有str方法的返回的是对象的地址
反射
提供了一种更加灵活的方式可以实现去 对象 中操作成员(以字符串的形式去 `对象` 中进行成员的操作)。
4个内置函数来支持反射:
getattr,去对象中获取成员 v2 = getattr(对象,"成员名称", 不存在时的默认值)
setattr,去对象中设置成员 setattr(对象,"成员名称",值)
hasattr,对象中是否包含成员 v1 = hasattr(对象,"成员名称") # True/False
delattr,删除对象中的成员 delattr(对象,"成员名称")
网络编程
url浏览器请求流程:
第一DNS的域名解析
第二建立TCP连接
第三发送http请求
第四服务器处理请求
第五服务器返回响应结果
第六关闭TCP连接
第七浏览器解析HTML
第八浏览器渲染
OSI 7层模型
应用层 规定数据的格式
表示层 对应用层数据的编码 压缩 分块 加密 等任务
会话层 与目标建立与中断连接
传输层 建立端口与端口的通信
网络层 标记目标ip信息
数据链路层 对数据进行分组,并设置源和目标mac地址
物理层 将二进制数据通过网线传输
TCP和UDP
协议:规定连接和收发数据的一些规定
OSI传输层除了定义端口信息外 常见的还可以指定TCP和UDP协议
UDP:用户数据协议,一个无连接简单面向数据包传输层协议
TCP:传输控制协议,是面向连接协议 三次握手 四次挥手
区别:
1)传送方式:get通过地址栏传输,post通过报文传输
2)传送长度:get参数有长度限制(受限于url长度),而post无限制
3)GET产生一个TCP数据包(对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200返回数据),
POST产生两个TCP数据包(对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok返回数据)
4)get请求参数会被完整保留在浏览历史记录里,而post中的参数不会被保留
5)在做数据查询时,建议用GET方式;而在做数据添加、修改或删除时,建议用post方式
接口测试cookie session token的区别
1、存放及使用:
1)Cookie 数据存放在客户的浏览器(客户端)上; Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
2)Session 数据放在服务器上;用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session,请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器,浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中。
3)Token 数据存放在客户端,是接口测试时的鉴权码,一般情况下登录后才可以获取到 Token,然后在每次请求接口时需要带上 Token 参数。
2、安全及性能:
1)Cookie 不是很安全,其他人是可以分析存放在本地的 Cookie 并进行 Cookie 欺骗;Session 更安全,考虑到安全应当使用 Session,在一定时间内保存在服务器上。可以将登录等重要信息存放为 Session;其他信息需要保存,可以放在 Cookie。
2)当访问增多,会比较影响服务器的性能,考虑到减轻服务器压力,应当适时选择使用 Cookie。
3)Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听和重放攻击,而 Session 就必须依赖链路层来保障通讯安全了。
tcp的四次挥手是什么:
客户端和服务端通信完毕后关闭连接时要进行四次挥手
第一次客户端发送一个FIN包申请断开连接并等待服务器确认
第二次挥手服务端回复一个ACK包表示接收到客户端关闭连接请求但是服务端还不能马上关闭连接需要检查是否还有未处理完的数据
第三次挥手服务端处理完所有数据给客户端发送FIN包表示可以断开连接
第四次挥手客户端回复ACK包断开连接
进程和线程
进程:
是计算机资源分配的最小单元(进程为线程提供资源 独立的内存单元)
进程在执行过程中拥有独立的内存单元,而该进程的多个线程共享内存,从而极大地提高了程序的运行效率。
计算密集型,用多进程,例如:大量的数据计算【累加计算示例】
线程:
是计算机中可以被cpu调度的最小单元(真正在工作 执行代码)
线程指在程序执行过程中,能够执行程序代码的一个执行单位,每个程序至少都有一个线程,也就是程序本身
IO密集型,用多线程,例如:文件读写、网络数据传输【下载抖音视频示例】
进程线程的区别:
打个比方:进程等于火车 线程等于车厢 乘客就是数据,线程是在进程下运行的单纯的车厢是无法运行的,一个进程包含多个线程 不同进程之间数据很难共享 ,同一进程下和不同线程数据可以共享,进程要比线程消耗更多的计算机资源多列火车比单列火车更耗资源
IO多路复用:
通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
在Linux操作系统化中 IO多路复用 有三种模式,分别是:select,poll,epoll。(windows 只支持select模式)

浙公网安备 33010602011771号