精心整理了 170 道 Python 面试题
目录
上下滑动查看更多
基础篇
1. 为什么学习 Python
2. 解释型和编译型语言的区别
3. 简述下 Python 中的字符串、列表、元组和字典
4. 简述上述数据类型的常用方法
5. 简述 Python 中的字符串编码
6.一行代码实现数值交换
7. is 和 == 的区别
8.Python 函数中的参数类型
9.`*arg` 和 `**kwarg` 作用
10.一行代码实现1-100之和
11.获取当前时间
12.PEP8 规范
13.Python 的深浅拷贝
14.查看下面代码的输出
15.可变类型与不可变类型
16.打印九九乘法表
17.filter、map、reduce 的作用
18.re 的 match 和 search 区别
19.面向对象中`__new__` 和 `__init__` 区别
20.三元运算规则
21.生成随机数
22.zip 函数用法
23.range 和 xrange 的区别
24.with 方法打开文件的作用
25.什么是正则的贪婪匹配
26.为什么不建议函数的默认参数传入可变对象
27.字符串转列表
28.字符串转整数
29.删除列表中的重复值
30.字符串单词统计
31.列表推导,求奇偶数
32.一行代码展开列表
33.实现二分法查找函数
34.字典和 json 转换
35.列表推导式、字典推导式和生成器
36.简述 read、readline、readlines 的区别
37.打乱一个列表
38.反转字符串
39.单下划线和双下划线的作用
40.新式类和旧式类
41.Python 面向对象中的继承有什么特点
42.super 函数的作用
43.类中的各种函数
44.如何判断是函数还是方法
45.isinstance 的作用以及与 type()的区别
46.单例模式与工厂模式
47.查看目录下的所有文件
48.计算1到5组成的互不重复的三位数
49.去除字符串首尾空格
50.去除字符串中间的空格
51. 字符串格式化方式
52. 将"hello world"转换为首字母大写"Hello World"(不使用 title 函数)
53. 一行代码转换列表中的整数为字符串
54. 合并两个元组到字典
55. 给出如下代码的输入,并简单解释
56. Python 中的反射
57. 实现一个简单的 API
58. metaclass 元类
59. sort 和 sorted 的区别
60. Python 中的 GIL
61. 产生8位随机密码
62. 输出原始字符
63. 列表内,字典按照 value 大小排序
64. 简述 any() 和 all() 方法
65. 反转整数
66. 函数式编程
67. 简述闭包
68. 简述装饰器
69. 协程的优点
70. 实现一个斐波那契数列
71. 正则切分字符串
72. yield 用法
73. 冒泡排序
74. 快速排序
75. requests 简介
76. 比较两个 json 数据是否相等
77. 读取键盘输入
78. enumerate
79. pass 语句
80. 正则匹配邮箱
81. 统计字符串中大写字母的数量
82. json 序列化时保留中文
83. 简述继承
84. 什么是猴子补丁
85. help() 函数和 dir() 函数
86. 解释 Python 中的`//`,`%`和`**`运算符
87. 主动抛出异常
88. tuple 和 list 转换
89. 简述断言
90. 什么是异步非阻塞
91. 什么是负索引
92. 退出 Python 后,内存是否全部释放
93. Flask 和 Django 的异同
94. 创建删除操作系统上的文件
95. 简述 logging 模块
96. 统计字符串中单词出现次数
97. 正则 re.complie 的作用
98. try except else finally 的意义
99.反转列表
100. 字符串中数字替换
综合篇:网络编程
101. 简述 OSI 七层协议
102. 三次握手、四次挥手的流程
103. 什么是 C/S 和 B/S 架构
104. TCP 和 UDP 的区别
105. 局域网和广域网
106. arp 协议
107. 什么是 socket?简述基于 TCP 协议的套接字通信流程
108. 简述 进程、线程、协程的区别以及应用场景
109. 如何使用线程池和进程池
110. 进程之间如何进行通信
111. 进程锁和线程锁
112. 什么是并发和并行
113. threading.local 的作用
114. 什么是域名解析
115. LVS 是什么及作用
116. Nginx 的作用
117. keepalived 及 HAProxy
118. 什么是 rpc
119. 从浏览器输入一个网址到展示网址页面的过程
120. 什么是cdn
综合篇:数据库和框架
121. 列举常见的数据库
122. 数据库设计三大范式
123. 什么是数据库事务
124. MySQL 索引种类
125. 数据库设计中一对多和多对多的应用场景
126. 简述触发器、函数、视图、存储过程
127. 常用 SQL 语句
128. 主键和外键的区别
129. 如何开启 MySQL 慢日志查询
130. MySQL 数据库备份命令
131. char 和 varchar 的区别
132. 最左前缀原则
133. 无法命中索引的情况
134. 数据库读写分离
135. 数据库分库分表
136. redis 和 memcached 比较
137. redis中数据库默认是多少个 db 及作用
138. redis 有哪几种持久化策略
139. redis 支持的过期策略
140. 如何保证 redis 中的数据都是热点数据
141. Python 操作 redis
142. 基于 redis 实现发布和订阅
143. 如何高效的找到 redis 中的某个 KEY
144. 基于 redis 实现先进先出、后进先出及优先级队列
145. redis 如何实现主从复制
146. 循环获取 redis 中某个非常大的列表数据
147. redis 中的 watch 的命令的作用
148. redis 分布式锁
149. http 协议
150. uwsgi,uWSGI 和 WSGI 的区别
151. HTTP 状态码
152. HTTP常见请求方式
153. 响应式布局
154. 实现一个简单的 AJAX 请求
155. 同源策略
156. 什么是 CORS
157. 什么是 CSRF
158. 前端实现轮询、长轮询
159. 简述 MVC 和 MTV
160. 接口的幂等性
161. Flask 框架的优势
162. 什么是 ORM
163. PV、UV 的含义
164. supervisor 的作用
165. 使用 ORM 和原生 SQL 的优缺点
166. 列举一些 django 的内置组件
167. 列举 Django 中执行原生 sql 的方法
168. cookie 和 session 的区别
169. beautifulsoup 模块的作用
170. Selenium 模块简述
基础篇
1. 为什么学习 Python
Python 语言简单易懂,上手容易,随着 AI 风潮,越来越火
2. 解释型和编译型语言的区别
编译型语言:把做好的源程序全部编译成二进制的可运行程序。然后,可直接运行这个程序。如:C,C++ 解释型语言:把做好的源程序翻译一句,然后执行一句,直至结束!如:Python, (Java 有些特殊,java程序也需要编译,但是没有直接编译称为机器语言,而是编译称为字节码,然后用解释方式执行字节码。)
3. 简述下 Python 中的字符串、列表、元组和字典
字符串(str):字符串是用引号括起来的任意文本,是编程语言中最常用的数据类型。列表(list):列表是有序的集合,可以向其中添加或删除元素。元组(tuple):元组也是有序集合,但是是无法修改的。即元组是不可变的。字典(dict):字典是无序的集合,是由 key-value 组成的。集合(set):是一组 key 的集合,每个元素都是唯一,不重复且无序的。
4. 简述上述数据类型的常用方法
字符串:
切片 mystr='luobodazahui' mystr[1:3] output 'uo'
format mystr2 = "welcome to luobodazahui, dear {name}" mystr2.format(name="baby") output 'welcome to luobodazahui, dear baby'
join 可以用来连接字符串,将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串。mylist = ['luo', 'bo', 'da', 'za', 'hui'] mystr3 = '-'.join(mylist) print(mystr3) outout 'luo-bo-da-za-hui'
replace String.replace(old,new,count) 将字符串中的 old 字符替换为 New 字符,count 为替换的个数 mystr4 = 'luobodazahui-haha' print(mystr4.replace('haha', 'good'))
output luobodazahui-good
split 切割字符串,得到一个列表
mystr5 = 'luobo,dazahui good'
# 以空格分割
print(mystr5.split())
# 以h分割
print(mystr5.split('h'))
# 以逗号分割
print(mystr5.split(','))
output
['luobo,dazahui', 'good']
['luobo,daza', 'ui good']
['luobo', 'dazahui good']
列表:
切片 同字符串
append 和 extend 向列表中国添加元素
mylist1 = [1, 2]
mylist2 = [3, 4]
mylist3 = [1, 2]
mylist1.append(mylist2)
print(mylist1)
mylist3.extend(mylist2)
print(mylist3)
outout
[1, 2, [3, 4]]
[1, 2, 3, 4]
删除元素 del:根据下标进行删除 pop:删除最后一个元素 remove:根据元素的值进行删除
mylist4 = ['a', 'b', 'c', 'd']
del mylist4[0]
print(mylist4)
mylist4.pop()
print(mylist4)
mylist4.remove('c')
print(mylist4)
output
['b', 'c', 'd']
['b', 'c']
['b']
元素排序 sort:是将list按特定顺序重新排列,默认为由小到大,参数 reverse=True 可改为倒序,由大到小。reverse:是将list逆置
mylist5 = [1, 5, 2, 3, 4]
mylist5.sort()
print(mylist5)
mylist5.reverse()
print(mylist5)
output
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]
字典:
清空字典 dict.clear()
dict1 = {'key1':1, 'key2':2}
dict1.clear()
print(dict1)
output
{}
指定删除 使用 pop 方法来指定删除字典中的某一项
dict1 = {'key1':1, 'key2':2}
d1 = dict1.pop('key1')
print(d1)
print(dict1)
output
1
{'key2': 2}
遍历字典
dict2 = {'key1':1, 'key2':2}
mykey = [key for key in dict2]
print(mykey)
myvalue = [value for value in dict2.values()]
print(myvalue)
key_value = [(k, v) for k, v in dict2.items() ]
print(key_value)
output
['key1', 'key2']
[1, 2]
[('key1', 1), ('key2', 2)]
fromkeys 用于创建一个新字典,以序列中元素做字典的键,value 为字典所有键对应的初始值
keys = ['zhangfei', 'guanyu', 'liubei', 'zhaoyun']
dict.fromkeys(keys, 0)
output
{'zhangfei': 0, 'guanyu': 0, 'liubei': 0, 'zhaoyun': 0}
5. 简述 Python 中的字符串编码
计算机在最初的设计中,采用了8个比特(bit)作为一个字节(byte)的方式。一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如果要表示更大的整数,就必须用更多的字节。最早,计算机只有 ASCII 编码,即只包含大小写英文字母、数字和一些符号,这些对于其他语言,如中文,日文显然是不够用的。后来又发明了Unicode,Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。UTF-8 是隶属于 Unicode 的可变长的编码方式。在 Python 中,以 Unicode 方式编码的字符串,可以使用 encode() 方法来编码成指定的 bytes,也可以通过 decode() 方法来把 bytes 编码成字符串。encode
"中文".encode('utf-8')
output
b'\xe4\xb8\xad\xe6\x96\x87'
decode
b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
output
'中文'
6.一行代码实现数值交换
1a = 1
2b = 2
3a, b = b, a
4print(a, b)
output
12 1
7. is 和 == 的区别
先来看个例子
c = d = [1,2]
e = [1,2]
print(c is d)
print(c == d)
print(c is e)
print(c == e)
output
True
True
False
True
== 是比较操作符,只是判断对象的值(value)是否一致,而 is 则判断的是对象之间的身份(内存地址)是否一致。对象的身份,可以通过 id() 方法来查看
id(c)
id(d)
id(e)
output
88748080
88748080
88558288
可以看出,只有 id 一致时,is 比较才会返回 True,而当 value 一致时,== 比较就会返回 True
8.Python 函数中的参数类型
位置参数,默认参数,可变参数,关键字参数
9.*arg
和 **kwarg
作用
允许我们在调用函数的时候传入多个实参
def test(*arg, **kwarg):if arg:print("arg:", arg)if kwarg:print("kearg:", kwarg)
test('ni', 'hao', key='world')
output
arg: ('ni', 'hao')
kearg: {'key': 'world'}
可以看出,*arg
会把位置参数转化为 tuple**kwarg
会把关键字参数转化为 dict
10.一行代码实现1-100之和
sum(range(1, 101))
11.获取当前时间
import time
import datetime
print(datetime.datetime.now())
print(time.strftime('%Y-%m-%d %H:%M:%S'))
output
2019-06-07 18:12:11.165330
2019-06-07 18:12:11
12.PEP8 规范
简单列举10条:尽量以免单独使用小写字母'l',大写字母'O',以及大写字母'I'等容易混淆的字母。函数命名使用全部小写的方式,可以使用下划线。常量命名使用全部大写的方式,可以使用下划线。使用 has 或 is 前缀命名布尔元素,如: is_connect = True; has_member = False 不要在行尾加分号, 也不要用分号将两条命令放在同一行。不要使用反斜杠连接行。顶级定义之间空2行, 方法定义之间空1行,顶级定义之间空两行。如果一个类不继承自其它类, 就显式的从object继承。内部使用的类、方法或变量前,需加前缀_
表明此为内部使用的。要用断言来实现静态类型检测。
13.Python 的深浅拷贝
浅拷贝
import copy
list1 = [1, 2, 3, [1, 2]]
list2 = copy.copy(list1)
list2.append('a')
list2[3].append('a')
print(list1, list2)
output
[1, 2, 3, [1, 2, 'a']] [1, 2, 3, [1, 2, 'a'], 'a']
能够看出,浅拷贝只成功”独立“拷贝了列表的外层,而列表的内层列表,还是共享的
深拷贝
import copy
list1 = [1, 2, 3, [1, 2]]
list3 = copy.deepcopy(list1)
list3.append('a')
list3[3].append('a')
print(list1, list3)
output
[1, 2, 3, [1, 2]] [1, 2, 3, [1, 2, 'a'], 'a']
深拷贝使得两个列表完全独立开来,每一个列表的操作,都不会影响到另一个
14.查看下面代码的输出
def num():return [lambda x:i*x for i in range(4)]
print([m(1) for m in num()])
output
[3, 3, 3, 3]
通过运行结果,可以看出 i 的取值为3,很神奇
15.可变类型与不可变类型
可变数据类型:list、dict、set
不可变数据类型:int/float、str、tuple
16.打印九九乘法表
for i in range(1, 10):for j in range(1, i+1):print("%s*%s=%s " %(i, j, i*j), end="")print()
output
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
print 函数,默认是会换行的,其有一个默认参数 end,如果像例子中,我们把 end 参数显示的置为"",那么 print 函数执行完后,就不会换行了,这样就达到了九九乘法表的效果了
17.filter、map、reduce 的作用
filter 函数用于过滤序列,它接收一个函数和一个序列,把函数作用在序列的每个元素上,然后根据返回值是True还是False决定保留还是丢弃该元素
mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list(filter(lambda x: x%2 == 1, mylist))
output
[1, 3, 5, 7, 9]
保留奇数列表
map 函数传入一个函数和一个序列,并把函数作用到序列的每个元素上,返回一个可迭代对象
mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list(map(lambda x: x*2, mylist))
output
[2, 4, 6, 8, 10, 12, 14, 16, 18]
reduce 函数用于递归计算,同样需要传入一个函数和一个序列,并把函数和序列元素的计算结果与下一个元素进行计算
from functools import reduce
reduce(lambda x, y: x+y, range(101))
output
5050
可以看出,上面的三个函数与匿名函数相结合使用,可以写出强大简洁的代码
18.re 的 match 和 search 区别
match()函数只检测要匹配的字符是不是在 string 的开始位置匹配,search()会扫描整个 string 查找匹配
19.面向对象中__new__
和 __init__
区别
__new__
是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例对象,是个静态方法。__init__
是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值,通常用在初始化一个类实例的时候,是一个实例方法
1、__new__
至少要有一个参数 cls,代表当前类,此参数在实例化时由 Python 解释器自动识别。2、__new__
必须要有返回值,返回实例化出来的实例,这点在自己实现__new__
时要特别注意,可以 return 父类(通过 super(当前类名, cls))__new__
出来的实例,或者直接是 object 的__new__
出来的实例。3、__init__
有一个参数 self,就是这个__new__
返回的实例,__init__
在__new__
的基础上可以完成一些其它初始化的动作,__init__
不需要返回值。4、如果__new__
创建的是当前类的实例,会自动调用__init__
函数,通过 return 语句里面调用的__new__
函数的第一个参数是 cls 来保证是当前类实例,如果是其他类的类名,;那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__
函数,也不会调用其他类的__init__
函数
20.三元运算规则
a, b = 1, 2
# 若果 a>b 成立 就输出 a-b 否则 a+b
h = a-b if a>b else a+b
output
3
21.生成随机数
print(random.random())
print(random.randint(1, 100))
print(random.uniform(1,5))
output
0.03765019937131564
18
1.8458555362279228
22.zip 函数用法
zip() 函数将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表
list1 = ['zhangfei', 'guanyu', 'liubei', 'zhaoyun']
list2 = [0, 3, 2, 4]
list(zip(list1, list2))
output
[('zhangfei', 0), ('guanyu', 3), ('liubei', 2), ('zhaoyun', 4)]
23.range 和 xrange 的区别
range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列。而 xrange 生成一个生成器,可以很大的节约内存
24.with 方法打开文件的作用
开文件在进行读写的时候可能会出现一些异常状况,如果按照常规的 f.open 写法,我们需要 try,except,finally,做异常判断,并且文件最终不管遇到什么情况,都要执行 finally f.close() 关闭文件,with 方法帮我们实现了 finally 中 f.close
25.什么是正则的贪婪匹配
Python 中默认是贪婪匹配模式
贪婪模式:正则表达式一般趋向于最大长度匹配
非贪婪模式:在整个表达式匹配成功的前提下,尽可能少的匹配
26.为什么不建议函数的默认参数传入可变对象
例如:
def test(L=[]):L.append('test')print(L)
output
test() # ['test']
test() # ['test', 'test']
默认参数是一个列表,是可变对象[],Python 在函数定义的时候,默认参数 L 的值就被计算出来了,是[],每次调用函数,如果 L 的值变了,那么下次调用时,默认参数的值就已经不再是[]了
27.字符串转列表
mystr = '1,2,3'
mystr.split(',')
output
['1', '2', '3']
28.字符串转整数
mylist = ['1', '2', '3']
list(map(lambda x: int(x), mylist))
output
[1, 2, 3]
29.删除列表中的重复值
mylist = [1, 2, 3, 4, 5, 5]
list(set(mylist))
30.字符串单词统计
from collections import Counter
mystr = 'sdfsfsfsdfsd,were,hrhrgege.sdfwe!sfsdfs'
Counter(mystr)
outputCounter({'s': 9,'d': 5,'f': 7,',': 2,'w': 2,'e': 5,'r': 3,'h': 2,'g': 2,'.': 1,'!': 1})
31.列表推导,求奇偶数
[x for x in range(10) if x%2 == 1]
output
[1, 3, 5, 7, 9]
32.一行代码展开列表
list1 = [[1,2],[3,4],[5,6]]
[j for i in list1 for j in i]
output
[1, 2, 3, 4, 5, 6]
33.实现二分法查找函数
二分查找算法也称折半查找,基本思想就是折半,对比大小后再折半查找,必须是有序序列才可以使用二分查找
递归算法
def binary_search(data, item):# 递归n = len(data)if n > 0:mid = n // 2if data[mid] == item:return Trueelif data[mid] > item:return binary_search(data[:mid], item)else:return binary_search(data[mid+1:], item)return False
list1 = [1,4,5,66,78,99,100,101,233,250,444,890]
binary_search(list1, 999)
非递归算法
def binary_search(data, item):# 非递归n = len(data)first = 0last = n - 1while first <= last:mid = (first + last)//2if data[mid] == item:return Trueelif data[mid] > item:last = mid - 1else:first = mid + 1return False
list1 = [1,4,5,66,78,99,100,101,233,250,444,890]
binary_search(list1, 99)
34.字典和 json 转换
字典转 json
import json
dict1 = {'zhangfei':1, "liubei":2, "guanyu": 4, "zhaoyun":3}
myjson = json.dumps(dict1)
myjson
output
'{"zhangfei": 1, "liubei": 2, "guanyu": 4, "zhaoyun": 3}'
json 转字典
mydict = json.loads(myjson)
mydict
output
{'zhangfei': 1, 'liubei': 2, 'guanyu': 4, 'zhaoyun': 3}
35.列表推导式、字典推导式和生成器
import random
td_list=[i for i in range(10)]
print("列表推导式", td_list, type(td_list))
ge_list = (i for i in range(10))
print("生成器", ge_list)
dic = {k:random.randint(4, 9)for k in ["a", "b", "c", "d"]}
print("字典推导式",dic,type(dic))
output
列表推导式 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <class 'list'>
生成器 <generator object <genexpr> at 0x0139F070>
字典推导式 {'a': 6, 'b': 5, 'c': 8, 'd': 9} <class 'dict'>
36.简述 read、readline、readlines 的区别
read 读取整个文件
readline 读取下一行,使用生成器方法
readlines 读取整个文件到一个迭代器以供我们遍历
37.打乱一个列表
list2 = [1, 2, 3, 4, 5, 6]
random.shuffle(list2)
print(list2)
output
[4, 6, 5, 1, 2, 3]
38.反转字符串
str1 = 'luobodazahui'
str1[::-1]
output
'iuhazadoboul'
39.单下划线和双下划线的作用
__foo__
:一种约定,Python 内部的名字,用来区别其他用户自定义的命名,以防冲突,就是例如__init__()
,__del__()
,__call__()
些特殊方法
_foo
:一种约定,用来指定变量私有。不能用 from module import * 导入,其他方面和公有变量一样访问
__foo
:这个有真正的意义:解析器用_classname__foo
来代替这个名字,以区别和其他类相同的命名,它无法直接像公有成员一样随便访问,通过对象名._
类名__xxx
这样的方式可以访问
40.新式类和旧式类
a. 在 python 里凡是继承了 object 的类,都是新式类
b. Python3 里只有新式类
c. Python2 里面继承 object 的是新式类,没有写父类的是经典类
d. 经典类目前在 Python 里基本没有应用
41.Python 面向对象中的继承有什么特点
a. 同时支持单继承与多继承,当只有一个父类时为单继承,当存在多个父类时为多继承
b. 子类会继承父类所有的属性和方法,子类也可以覆盖父类同名的变量和方法
c. 在继承中基类的构造(__init__()
)方法不会被自动调用,它需要在其派生类的构造中专门调用
d. 在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别于在类中调用普通函数时并不需要带上 self 参数
42.super 函数的作用
super() 函数是用于调用父类(超类)的一个方法
class A():def funcA(self):print("this is func A")class B(A):def funcA_in_B(self):super(B, self).funcA()def funcC(self):print("this is func C")ins = B()
ins.funcA_in_B()
ins.funcC()
output
this is func A
this is func C
43.类中的各种函数
主要分为实例方法、类方法和静态方法
实例方法
定义:第一个参数必须是实例对象,该参数名一般约定为“self”,通过它来传递实例的属性和方法(也可以传类的属性和方法)
调用:只能由实例对象调用
类方法
定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法)
调用:实例对象和类对象都可以调用
静态方法
定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法
调用:实例对象和类对象都可以调用
静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,主要是一些逻辑属于类,但是和类本身没有交互。即在静态方法中,不会涉及到类中的方法和属性的操作。可以理解为将静态方法存在此类的名称空间中
类方法是将类本身作为对象进行操作的方法。他和静态方法的区别在于:不管这个方式是从实例调用还是从类调用,它都用第一个参数把类传递过来
44.如何判断是函数还是方法
与类和实例无绑定关系的 function 都属于函数(function)
与类和实例有绑定关系的 function 都属于方法(method)
普通函数:
def func1():pass
print(func1)
output
<function func1 at 0x01379348>
类中的函数:class People(object):def func2(self):pass@staticmethoddef func3():pass@classmethoddef func4(cls):pass
people = People()
print(people.func2)
print(people.func3)
print(people.func4)
output
<bound method People.func2 of <__main__.People object at 0x013B8C90>>
<function People.func3 at 0x01379390>
<bound method People.func4 of <class '__main__.People'>>
45.isinstance 的作用以及与 type()的区别
isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()
区别:
type() 不会认为子类是一种父类类型,不考虑继承关系
isinstance() 会认为子类是一种父类类型,考虑继承关系
class A(object):passclass B(A):passa = A()b = B()print(isinstance(a, A))print(isinstance(b, A))print(type(a) == A)
print(type(b) == A)
output
True
True
True
False
46.单例模式与工厂模式
单例模式:主要目的是确保某一个类只有一个实例存在
工厂模式:包涵一个超类,这个超类提供一个抽象化的接口来创建一个特定类型的对象,而不是决定哪个对象可以被创建
47.查看目录下的所有文件
import os
print(os.listdir('.'))
48.计算1到5组成的互不重复的三位数
# 1到5组成的互不重复的三位数k = 0for i in range(1, 6):for j in range(1, 6):for z in range(1, 6):if (i != j) and (i != z) and (j != z):k += 1if k%6:print("%s%s%s" %(i, j, z), end="|")else:print("%s%s%s" %(i, j, z))
output
123|124|125|132|134|135142|143|145|152|153|154213|214|215|231|234|235241|243|245|251|253|254312|314|315|321|324|325341|342|345|351|352|354412|413|415|421|423|425431|432|435|451|452|453512|513|514|521|523|524
531|532|534|541|542|543
49.去除字符串首尾空格
str1 = " hello nihao "
str1.strip()
output
'hello nihao'
50.去除字符串中间的空格
str2 = "hello you are good"
print(str2.replace(" ", ""))
"".join(str2.split(" "))
output
helloyouaregood
'helloyouaregood'
51. 字符串格式化方式
使用 % 操作符
print("This is for %s" % "Python")
print("This is for %s, and %s" %("Python", "You"))
output
This is for Python
This is for Python, and You
str.format
在 Python3 中,引入了这个新的字符串格式化方法
print("This is my {}".format("chat"))
print("This is {name}, hope you can {do}".format(name="zhouluob", do="like"))
output
This is my chat
This is zhouluob, hope you can like
f-strings
在 Python3-6 中,引入了这个新的字符串格式化方法
name = "luobodazahui"
print(f"hello {name}")
output
hello luobodazahui
一个复杂些的例子:
def mytest(name, age):return f"hello {name}, you are {age} years old!"
people = mytest("luobo", 20)
print(people)
output
hello luobo, you are 20 years old!
52. 将"hello world"转换为首字母大写"Hello World"(不使用 title 函数)
str1 = "hello world"
print(str1.title())
" ".join(list(map(lambda x: x.capitalize(), str1.split(" "))))
output
Hello World
'Hello World'
53. 一行代码转换列表中的整数为字符串
如:[1, 2, 3] -> ["1", "2", "3"]
list1 = [1, 2, 3]
list(map(lambda x: str(x), list1))
output
['1', '2', '3']
54. 合并两个元组到字典
如:("zhangfei", "guanyu"),(66, 80) -> {'zhangfei': 66, 'guanyu': 80}
a = ("zhangfei", "guanyu")
b = (66, 80)
dict(zip(a,b))
output
{'zhangfei': 66, 'guanyu': 80}
55. 给出如下代码的输入,并简单解释
例子1:
a = (1,2,3,[4,5,6,7],8)
a[3] = 2
output
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-35-59469d550eb0> in <module>1 a = (1,2,3,[4,5,6,7],8)
----> 2 a[3] = 23 #aTypeError: 'tuple' object does not support item assignment
例子2:
a = (1,2,3,[4,5,6,7],8)
a[3][2] = 2
a
output
(1, 2, 3, [4, 5, 2, 7], 8)
从例子1的报错中也可以看出,tuple 是不可变类型,不能改变 tuple 里的元素,例子2中,list 是可变类型,改变其元素是允许的
56. Python 中的反射
反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!
简单理解就是用来判断某个字符串是什么,是变量还是方法
class NewClass(object):def __init__(self, name, male):self.name = nameself.male = maledef myname(self):print(f'My name is {self.name}')def mymale(self):print(f'I am a {self.male}')people = NewClass('luobo', 'boy')
print(hasattr(people, 'name'))
print(getattr(people, 'name'))
setattr(people, 'male', 'girl')
print(getattr(people, 'male'))
output
True
luobo
girl
getattr,hasattr,setattr,delattr 对模块的修改都在内存中进行,并不会影响文件中真实内容
57. 实现一个简单的 API
使用 flask 构造 web 服务器
from flask import Flask, requestapp = Flask(__name__)@app.route('/', methods=['POST'])def simple_api():result = request.get_json()return resultif __name__ == "__main__":app.run()
58. metaclass 元类
类与实例:
首先定义类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例
类与元类:
先定义元类, 根据 metaclass 创建出类,所以:先定义 metaclass,然后创建类
class MyMetaclass(type):def __new__(cls, class_name, class_parents, class_attr):class_attr['print'] = "this is my metaclass's subclass %s" %class_namereturn type.__new__(cls, class_name, class_parents, class_attr)
class MyNewclass(object, metaclass=MyMetaclass):passmyinstance = MyNewclass()
myinstance.print
output
"this is my metaclass's subclass MyNewclass"
59. sort 和 sorted 的区别
sort() 是可变对象列表(list)的方法,无参数,无返回值,sort() 会改变可变对象
dict1 = {'test1':1, 'test2':2}
list1 = [2, 1, 3]
print(list1.sort())
list1
output
None
[1, 2, 3]
sorted() 是产生一个新的对象。sorted(L) 返回一个排序后的L,不改变原始的L,sorted() 适用于任何可迭代容器
dict1 = {'test1':1, 'test2':2}
list1 = [2, 1, 3]
print(sorted(dict1))print(sorted(list1))
output
['test1', 'test2']
[1, 2, 3]
60. Python 中的 GIL
GIL 是 Python 的全局解释器锁,同一进程中假如有多个线程运行,一个线程在运行 Python 程序的时候会占用 Python 解释器(加了一把锁即 GIL),使该进程内的其他线程无法运行,等该线程运行完后其他线程才能运行。如果线程运行过程中遇到耗时操作,则解释器锁解开,使其他线程运行。所以在多线程中,线程的运行仍是有先后顺序的,并不是同时进行
61. 产生8位随机密码
import random
"".join(random.choice(string.printable[:-7]) for i in range(8))
output
'd5^NdNJp'
62. 输出原始字符
print('hello\nworld')
print(b'hello\nworld')
print(r'hello\nworld')
output
hello
world
b'hello\nworld'
hello\nworld
63. 列表内,字典按照 value 大小排序
list1 = [{'name': 'guanyu', 'age':29},{'name': 'zhangfei', 'age': 28},{'name': 'liubei', 'age':31}]
sorted(list1, key=lambda x:x['age'])
output
[{'name': 'zhangfei', 'age': 28},
{'name': 'guanyu', 'age': 29},
{'name': 'liubei', 'age': 31}]
64. 简述 any() 和 all() 方法
all 如果存在 0 Null False 返回 False,否则返回 True;any 如果都是 0,None,False,Null 时,返回 True
print(all([1, 2, 3, 0]))
print(all([1, 2, 3]))
print(any([1, 2, 3, 0]))
print(any([0, None, False]))
output
False
True
True
False
65. 反转整数
def reverse_int(x):if not isinstance(x, int):return Falseif -10 < x < 10:return xtmp = str(x)if tmp[0] != '-':tmp = tmp[::-1]return int(tmp)else:tmp = tmp[1:][::-1]x = int(tmp)return -x
reverse_int(-23837)
output
-73832
首先判断是否是整数,再判断是否是一位数字,最后再判断是不是负数
66. 函数式编程
函数式编程是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。由于 Python 允许使用变量,因此,Python 不是纯函数式编程语言
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
函数作为返回值例子:
def sum(*args):def inner_sum():tmp = 0for i in args:tmp += ireturn tmpreturn inner_summysum = sum(2, 4, 6)print(type(mysum))
mysum()
output
<class 'function'>
12
67. 简述闭包
如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure) 附上函数作用域图片
闭包特点
1.必须有一个内嵌函数
2.内嵌函数必须引用外部函数中的变量
3.外部函数的返回值必须是内嵌函数
68. 简述装饰器
装饰器是一种特殊的闭包,就是在闭包的基础上传递了一个函数,然后覆盖原来函数的执行入口,以后调用这个函数的时候,就可以额外实现一些功能了
一个打印 log 的例子:
import timedef log(func):def inner_log(*args, **kw):print("Call: {}".format(func.__name__))return func(*args, **kw)return inner_log@log
def timer():print(time.time())timer()
output
Call: timer
1560171403.5128365
本质上,decorator就是一个返回函数的高阶函数
69. 协程的优点
子程序切换不是线程切换,而是由程序自身控制
没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显
不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁
70. 实现一个斐波那契数列
斐波那契数列:
又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)
生成器法:
def fib(n):if n == 0:return Falseif not isinstance(n, int) or (abs(n) != n): # 判断是正整数return Falsea, b = 0, 1while n:a, b = b, a+bn -= 1yield a[i for i in fib(10)]
output
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
递归法:
def fib(n):if n == 0:return Falseif not isinstance(n, int) or (abs(n) != n):return Falseif n <= 1:return nreturn fib(n-1)+ fib(n-2)[fib(i) for i in range(1, 11)]
output
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
71. 正则切分字符串
import re
str1 = 'hello world:luobo dazahui'
result = re.split(r":| ", str1)
print(result)
output
['hello', 'world', 'luobo', 'dazahui']
72. yield 用法
yield 是用来生成迭代器的语法,在函数中,如果包含了 yield,那么这个函数就是一个迭代器。当代码执行至 yield 时,就会中断代码执行,直到程序调用 next() 函数时,才会在上次 yield 的地方继续执行
def foryield():print("start test yield")while True:result = yield 5print("result:", result)
g = foryield()
print(next(g))
print("*"*20)
print(next(g))
output
start test yield
5
********************
result: None
5
可以看到,第一个调用 next() 函数,程序只执行到了 "result = yield 5" 这里,同时由于 yield 中断了程序,所以 result 也没有被赋值,所以第二次执行 next() 时,result 是 None
73. 冒泡排序
list1 = [2, 5, 8, 9, 3, 11]def paixu(data, reverse=False):if not reverse:for i in range(len(data) - 1):for j in range(len(data) - 1 - i):if data[j] > data[j+1]:data[j], data[j+1] = data[j+1], data[j]return dataelse:for i in range(len(data) - 1):for j in range(len(data) - 1 - i):if data[j] < data[j+1]:data[j], data[j+1] = data[j+1], data[j]return dataprint(paixu(list1, reverse=True))
output
[11, 9, 8, 5, 3, 2]
74. 快速排序
快排的思想:首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序,之后再递归排序两边的数据
挑选基准值:从数列中挑出一个元素,称为"基准"(pivot)
分割:重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(与基准值相等的数可以到任何一边)
在这个分割结束之后,对基准值的排序就已经完成
递归排序子序列:递归地将小于基准值元素的子序列和大于基准值元素的子序列排序
list1 = [8, 5, 1, 3, 2, 10, 11, 4, 12, 20]def partition(arr,low,high): i = ( low-1 ) # 最小元素索引pivot = arr[high] for j in range(low , high): # 当前元素小于或等于 pivot if arr[j] <= pivot: i = i+1 arr[i],arr[j] = arr[j],arr[i] arr[i+1],arr[high] = arr[high],arr[i+1] return ( i+1 )def quicksort(arr,low,high): if low < high: pi = partition(arr,low,high) quicksort(arr, low, pi-1) quicksort(arr, pi+1, high) quicksort(list1, 0, len(list1)-1)print(list1)
output
[1, 2, 3, 4, 5, 8, 10, 11, 12, 20]
75. requests 简介
该库是发起 HTTP 请求的强大类库,调用简单,功能强大
import requestsurl = "http://www.luobodazahui.top"response = requests.get(url) # 获得请求response.encoding = "utf-8" # 改变其编码html = response.text # 获得网页内容binary__content = response.content # 获得二进制数据raw = requests.get(url, stream=True) # 获得原始响应内容headers = {'user-agent': 'my-test/0.1.1'} # 定制请求头
r = requests.get(url, headers=headers)cookies = {"cookie": "# your cookie"} # cookie的使用
r = requests.get(url, cookies=cookies)
76. 比较两个 json 数据是否相等
dict1 = {"zhangfei": 12, "guanyu": 13, "liubei": 18}dict2 = {"zhangfei": 12, "guanyu": 13, "liubei": 18}def compare_dict(dict1, dict2):issame = []for k in dict1.keys():if k in dict2:if dict1[k] == dict2[k]:issame.append(1)else:issame.append(2)else:issame.append(3)print(issame)sum_except = len(issame)sum_actually = sum(issame)if sum_except == sum_actually:print("this two dict are same!")return Trueelse:print("this two dict are not same!")return Falsetest = compare_dict(dict1, dict2)
output
[1, 1, 1]
this two dict are same!
77. 读取键盘输入
input() 函数
def forinput():input_text = input()print("your input text is: ", input_text)
forinput()
output
hello
your input text is: hello
78. enumerate
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中
data1 = ['one', 'two', 'three', 'four']
for i, enu in enumerate(data1):print(i, enu)
output
0 one
1 two
2 three
3 four
79. pass 语句
pass 是空语句,是为了保持程序结构的完整性。pass 不做任何事情,一般用做占位语句
def forpass(n):if n == 1:passelse:print('not 1')
forpass(1)
80. 正则匹配邮箱
import re
email_list= ["test01@163.com","test02@163.123", ".test03g@qq.com", "test04@gmail.com" ]
for email in email_list:ret = re.match("[\w]{4,20}@(.*)\.com$",email)if ret:print("%s 是符合规定的邮件地址,匹配后结果是:%s" % (email,ret.group()))else:print("%s 不符合要求" % email)
output
test01@163.com 是符合规定的邮件地址,匹配后结果是:test01@163.com
test02@163.123 不符合要求
.test03g@qq.com 不符合要求
test04@gmail.com 是符合规定的邮件地址,匹配后结果是:test04@gmail.com
81. 统计字符串中大写字母的数量
str2 = 'werrQWSDdiWuW'
counter = 0
for i in str2:if i.isupper():counter += 1
print(counter)
output
6
82. json 序列化时保留中文
普通序列化:
import json
dict1 = {'name': '萝卜', 'age': 18}
dict1_new = json.dumps(dict1)
print(dict1_new)
output
{"name": "\u841d\u535c", "age": 18}
保留中文
import json
dict1 = {'name': '萝卜', 'age': 18}
dict1_new = json.dumps(dict1, ensure_ascii=False)
print(dict1_new)
output
{"name": "萝卜", "age": 18}
83. 简述继承
一个类继承自另一个类,也可以说是一个孩子类/派生类/子类,继承自父类/基类/超类,同时获取所有的类成员(属性和方法)
继承使我们可以重用代码,并且还可以更方便地创建和维护代码
Python 支持以下类型的继承:
单继承- 一个子类类继承自单个基类
多重继承- 一个子类继承自多个基类
多级继承- 一个子类继承自一个基类,而基类继承自另一个基类
分层继承- 多个子类继承自同一个基类
混合继承- 两种或两种以上继承类型的组合
84. 什么是猴子补丁
猴子补丁是指在运行时动态修改类和模块
猴子补丁主要有以下几个用处:
在运行时替换方法、属性等
在不修改第三方代码的情况下增加原来不支持的功能
在运行时为内存中的对象增加 patch 而不是在磁盘的源代码中增加
85. help() 函数和 dir() 函数
help() 函数返回帮助文档和参数说明:
help(dict)
output
Help on class dict in module builtins:class dict(object)| dict() -> new empty dictionary| dict(mapping) -> new dictionary initialized from a mapping object's| (key, value) pairs| dict(iterable) -> new dictionary initialized as if via:| d = {}| for k, v in iterable:| d[k] = v| dict(**kwargs) -> new dictionary initialized with the name=value pairs| in the keyword argument list. For example: dict(one=1, two=2)
......
dir() 函数返回对象中的所有成员 (任何类型)
dir(dict)
output
['__class__','__contains__','__delattr__','__delitem__','__dir__','__doc__','__eq__','__format__','__ge__','__getattribute__','__getitem__',
......
86. 解释 Python 中的//
,%
和**
运算符
//
运算符执行地板除法,返回结果的整数部分 (向下取整)
%
是取模符号,返回除法后的余数
**
符号表示取幂. a**b 返回 a 的 b 次方
print(5//3)
print(5/3)
print(5%3)
print(5**3)
output
1
1.6666666666666667
2
125
87. 主动抛出异常
使用 raise
def test_raise(n):if not isinstance(n, int):raise Exception('not a int type')else:print('good')
test_raise(8.9)
output
---------------------------------------------------------------------------Exception Traceback (most recent call last)<ipython-input-262-b45324f5484e> in <module>4 else:5 print('good')----> 6 test_raise(8.9)<ipython-input-262-b45324f5484e> in test_raise(n)1 def test_raise(n):2 if not isinstance(n, int):
----> 3 raise Exception('not a int type')4 else:5 print('good')Exception: not a int type
88. tuple 和 list 转换
tuple1 = (1, 2, 3, 4)
list1 = list(tuple1)
print(list1)
tuple2 = tuple(list1)
print(tuple2)
output
[1, 2, 3, 4](1, 2, 3, 4)
89. 简述断言
Python 的断言就是检测一个条件,如果条件为真,它什么都不做;反之它触发一个带可选错误信息的 AssertionError
def testassert(n):assert n == 2, "n is not 2"print('n is 2')
testassert(1)
output
---------------------------------------------------------------------------AssertionError Traceback (most recent call last)<ipython-input-268-a9dfd6c79e73> in <module>2 assert n == 2, "n is not 2"3 print('n is 2')----> 4 testassert(1)<ipython-input-268-a9dfd6c79e73> in testassert(n)1 def testassert(n):
----> 2 assert n == 2, "n is not 2"3 print('n is 2')4 testassert(1)AssertionError: n is not 2
90. 什么是异步非阻塞
同步异步指的是调用者与被调用者之间的关系
所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回,一旦调用返回,就得到了返回值
异步的概念和同步相对,调用在发出之后,这个调用就直接返回了,所以没有返回结果。当该异步功能完成后,被调用者可以通过状态、通知或回调来通知调用者
阻塞非阻塞是线程或进程之间的关系
阻塞调用是指调用结果返回之前,当前线程会被挂起(如遇到io操作)。调用线程只有在得到结果之后才会返回。函数只有在得到结果之后才会将阻塞的线程激活
非阻塞和阻塞的概念相对应,非阻塞调用指在不能立刻得到结果之前也会立刻返回,同时该函数不会阻塞当前线程
91. 什么是负索引
Python 中的序列是有索引的,它由正数和负数组成。正的数字使用'0'作为第一个索引,'1'作为第二个索引,以此类推
负数的索引从'-1'开始,表示序列中的最后一个索引,' - 2'作为倒数第二个索引,依次类推
92. 退出 Python 后,内存是否全部释放
不是的,那些具有对象循环引用或者全局命名空间引用的变量,在 Python 退出时往往不会被释放
另外不会释放 C 库保留的部分内容
93. Flask 和 Django 的异同
Flask 是 “microframework”,主要用来编写小型应用程序,不过随着 Python 的普及,很多大型程序也在使用 Flask。同时,在 Flask 中,我们必须使用外部库
Django 适用于大型应用程序。它提供了灵活性,以及完整的程序框架和快速的项目生成方法。可以选择不同的数据库,URL结构,模板样式等
94. 创建删除操作系统上的文件
import os
f = open('test.txt', 'w')
f.close()
os.listdir()
os.remove('test.txt')
95. 简述 logging 模块
logging 模块是 Python 内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比 print,具备如下优点:
可以通过设置不同的日志等级,在 release 版本中只输出重要信息,而不必显示大量的调试信息
print 将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据;logging 则可以由开发者决定将信息输出到什么地方,以及怎么输出
简单配置:
import logging
logging.debug("debug log")
logging.info("info log")
logging.warning("warning log")
logging.error("error log")
logging.critical("critica log")
output
WARNING:root:warning log
ERROR:root:error log
CRITICAL:root:critica log
默认情况下,只显示了大于等于WARNING级别的日志。logging.basicConfig()函数调整日志级别、输出格式等
96. 统计字符串中单词出现次数
from collections import Counter
str1 = "nihsasehndciswemeotpxc"
print(Counter(str1))
output
Counter({'s': 3, 'e': 3, 'n': 2, 'i': 2, 'h': 2, 'c': 2, 'a': 1, 'd': 1, 'w': 1, 'm': 1, 'o': 1, 't': 1, 'p': 1, 'x': 1})
97. 正则 re.complie 的作用
re.compile 是将正则表达式编译成一个对象,加快速度,并重复使用
98. try except else finally 的意义
try..except..else 没有捕获到异常,执行 else 语句
try..except..finally 不管是否捕获到异常,都执行 finally 语句
99.反转列表
使用切片:
$ python -m timeit -n 1000000 -s 'import numpy as np' 'mylist=list(np.arange(0, 200))' 'mylist[::-1]'
1000000 loops, best of 5: 15.6 usec per loop
使用 reverse():
$ python -m timeit -n 1000000 -s 'import numpy as np' 'mylist=list(np.arange(0, 200))' 'mylist.reverse()'
1000000 loops, best of 5: 10.7 usec per loop
这两种方法都可以反转列表,但需要注意的是内置函数 reverse() 会更改原始列表,而切片方法会创建一个新列表。
显然,内置函数 reverse() 比列表切片方法更快!
100. 字符串中数字替换
使用 re 正则替换
import re
str1 = '我是周萝卜,今年18岁'
result = re.sub(r"\d+","20",str1)
print(result)
output
我是周萝卜,今年20岁
综合篇:网络编程
101. 简述 OSI 七层协议
是网络传输协议,人为的把网络传输的不同阶段划分成不同的层次
七层划分为:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
五层划分为:应用层、传输层、网络层、数据链路层、物理层
物理层:网线,电缆等物理设备
数据链路层:Mac 地址
网络层:IP 地址
传输层:TCP,UDP 协议
应用层:FTP 协议,Email,WWW 等
102. 三次握手、四次挥手的流程
都发生在传输层
三次握手:
TCP 协议是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接。TCP 标志位(位码),有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急) Sequence number(顺序号码) Acknowledge number(确认号码) 第一次握手:主机 A 发送位码为 syn=1,随机产生 seq number=1234567 的数据包到服务器,并进入 SYN_SEND 状态,主机 B 由 SYN=1 知道,A 要求建立联机
第二次握手:主机 B 收到请求后要确认联机信息,向 A 发送 ack number=(主机 A 的 seq+1),syn=1,ack=1,随机产生 seq=7654321 的包,并进入 SYN_RECV 状态
第三次握手:主机 A 收到后检查 ack number 是否正确,即第一次发送的 seq number+1,以及位码 ack 是否为 1,若正确,主机 A 会再发送 ack number=(主机 B 的 seq+1),ack=1,主机 B 收到后确认 seq 值与 ack=1 则连接建立成功,两个主机均进入 ESTABLISHED 状态
以上完成三次握手,主机 A 与主机 B 开始传送数据
四次挥手:
因为 TCP 连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向的连接。收到一个 FIN 只意味着这一方向上没有数据流动,一个 TCP 连接在收到一个 FIN 后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭
服务器 A 发送一个 FIN,用来关闭 A 到服务器 B 的数据传送。服务器 B 收到这个 FIN,它发回一个 ACK,确认序号为收到的序号加1。和 SYN 一样,一个 FIN 将占用一个序号
服务器 B 关闭与服务器 A 的连接,发送一个 FIN 给服务器 A
服务器 A 发回 ACK 报文确认,并将确认序号设置为收到序号加1
....博主太懒了字数太多了,不想写了....文章已经做成PDF,有需要的朋友可以私信我免费获取!
精心整理了 170 道 Python 面试题相关推荐
- 精心整理170道Python面试题,建议先收藏(二)
简介: 精心整理170道Python面试题,建议先收藏(二) 51. 字符串格式化方式 使用 % 操作符 print("This is for %s" % "Python ...
- python笔试题110题_吐血整理:110道python面试题(带答案)
原博文 2020-06-22 05:23 − 吐血整理:110道python面试题(带答案) 一.总结 一句话总结: 人生如负重致远不可急躁,但是要抓紧干活. 1.一行代码实现1--100之和? su ...
- 精心整理 170 道 Python 面试题
精心整理的 Python 相关的基础知识,用于面试,或者平时复习,都是很好的!废话不多说,直接开搞 基础篇 1. 为什么学习 Python 2. 解释型和编译型语言的区别 3. 简述下 Python ...
- 怒肝 200 道 Python 面试题,我悟了!
大家好,我是 Rocky0429. 对于 Python 的学习,很多小伙伴和我说不知道自己现在什么水平,也不知道现在自己算是到了哪个阶段.其实很简单,那句话怎么说来着,实践是检验真理的唯一标准.怎么实 ...
- 三年python面试题_300道Python面试题
原标题:300道Python面试题 Python 工程师也分不同的技术岗位,初级.中级与高级开发工程师需要具备的技能也不同. 然而,无论是零经验还是 Python 老司机,对待每一次面试与笔试,都不能 ...
- cpython python 区别面试_python基础教程之千万不要错过这几道Python面试题
第1题: python下多线程的限制以及多进程中传递参数的方式? python多线程有个全局解释器锁(global interpreter lock),简称GIL,这个GIL并不是python的特性, ...
- 点开瞅瞅,再来几道Python面试题吧,Python面试题No20
文章目录 本面试题题库,由公号:非本科程序员 整理发布 第1题:如何理解 Django 被称为 MTV 模式? 第2题:解释下什么是 ORM 以及它的优缺点是什么? 第3题:Django 系统中如何配 ...
- 史无前例的这个 GitHub 汇总了 300 道 Python 面试题
对于机器学习算法工程师而言,是不可或缺的语言,它的优美与简洁令人无法自拔.那么你了解过Python编程面试题吗?从Python基础到网页爬虫你是否能全方位Hold住?今天,机器之心为读者们推荐一个Gi ...
- python面试题及答案-50道Python面试题集锦(附答案)
原标题:50道Python面试题集锦(附答案) Python是目前编程领域最受欢迎的语言.在本文中,我将总结Python面试中最常见的50个问题.每道题都提供参考答案,希望能够帮助你在2019年求职面 ...
最新文章
- wdcp php5.3 pdo_mysql,WDCP常用组件(memcache、mysqli、PDO_MYSQL、mysql innodb、libmcrypt、php zip)的安装方法...
- OpenCV中向量是可以转化为MAT类型的~
- 为什么世界需要 OpenStreetMap 开源道路地图
- 日常工作部门及体系相关单词
- 1052 卖个萌 (20 分)
- activiti创建子流程_OA流程图绘制指南
- 类构造函数(Constructor)单冒号:用法
- Alluxio部署(local模式)
- Leetcode 814.二叉树剪枝
- JNI系列(2):jstring操作
- Linux下的通用打开命令
- 暴力解决配置HTTPS后无法使用Hermit
- 侮辱性极强!6年编发无数反诈骗新闻,90后小编竟被骗了5万...
- Google 的浏览器安全手册
- 苹果手机该如何拍摄证件照
- 微信做图小程序有哪些_有哪些微信小程序值得推荐?
- 生产环境CPU占用飙高问题解决
- 昨天发现的一些ip黑名单
- 免费的压缩/解压缩软件
- Java编程实现快速傅里叶变换FFT