Python面试重点(进阶篇)
注意:只有必答题部分计算分值,补充题不计算分值。
第一部分 必答题
-
简述 OSI 7层模型及其作用?(2分)
应用层 表示层 会话层 传输层 端口 udp tcp 四层交换机 四层路由器 网络层 Ipv4 路由器 三层交换机 数据链路层 mac arp协议 网卡 交换机 物理层
-
简述 TCP三次握手、四次回收的流程。(3分)
# 1.三次握手是tcp协议建立连接的过程 # 2.由客户端发起一个syn请求,服务端接收并回复 (syn\ack) # 客户端收到ack和syn之后再回复一个ack # 3.在原生的socket代码中三次握手是由accept connect 2.四次挥手是tcp协议断开连接的过程 由客户端发起一个seq断开请求 服务器接到请求后回复ack参数,表示知道了,但是这是单方面的断开服务器还可以给客户端发送数据 服务器也给客户端发送seq请求,客户端接到请求后,会发送ack参数给服务器表示同意断开。到目前为止完成四次挥手
-
TCP和UDP的区别?(3分)
tcp:面向连接,可靠,速度慢,长度不受限,全双工,流式传输 udp 无连接 面向数据报 不可靠 速度快 长度受限制 一对一 一对多 多对多
-
什么是黏包?(2分)
数据传输过程由于数据大或者数据传输频率快导致数据不准确
-
什么 B/S 和 C/S 架构?(2分)
B/S:浏览器和服务器 C/S:客户端和服务端
-
请实现一个简单的socket编程(客户端和服务端可以进行收发消息)(3分)
sever端 import socket sk = socket.socket() sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 sk.listen() #监听链接 conn,addr = sk.accept() #接受客户端链接 ret = conn.recv(1024) #接收客户端信息 print(ret) #打印客户端信息 conn.send(b'hi') #向客户端发送信息 conn.close() #关闭客户端套接字 sk.close() #关闭服务器套接字(可选) client端 import socket sk = socket.socket() # 创建客户套接字 sk.connect(('127.0.0.1',8898)) # 尝试连接服务器 sk.send(b'hello!') ret = sk.recv(1024) # 对话(发送/接收) print(ret) sk.close() # 关闭客户套接字
-
简述进程、线程、协程的区别?(3分)
进程,线程,协程的区别:三个都可以提高并发 - 进程是计算机分配资源的最小单位;线程是计算机中cpu 调度的最小单位 - 协程又称为“微线程”,是基于代码创造出来的,而进程和线程都是计算机中真实存在的,一个进程可以有多个线程,一个线程可以创造多个协程 - 计算密集型:多进程 - io密集型:多线程或协程+io切换 - 单纯的协程没有办法提高并发,只是代码之间的来回切换,叫上io才有意义
-
什么是GIL锁?(2分)
GIL,全局解释器锁
同一时刻保证一个进程中只有一个线程可以被cpu调度,所以在使用Python开发时要注意: 计算密集型,用多进程. IO密集型,用多线程.
-
进程之间如何进行通信?(2分)
ipc通信
-
Python如何使用线程池、进程池?(2分)
import time from concurrent.futures import ThreadPoolExecutor import threading lock=threading.RLock() def start(i,n): print(id(lock)) time.sleep(1) with lock: print("任务1") fool=ThreadPoolExecutor(10) for i in range(100): fool.submit(start,i,1) print("end") fool.shutdown(True) print("所有任务执行结束") # import time # from concurrent.futures import ProcessPoolExecutor # # def tst(i): # time.sleep(1) # print("任务") # # if __name__ == '__main__': # # fool=ProcessPoolExecutor(10) # for i in range(100): # fool.submit(tst,i) # print("end") # fool.shutdown() # print("所有任务结束")
-
请通过yield关键字实现一个协程? (2分)
from gevent import monkey monkey.patch_all() import gevent import time def fun1(): print(1) yield 2 def fun2(): print(3) yield 4 f1=fun1().__next__() f2=fun2().__next__() t1 = gevent.spawn(fun1) t2 = gevent.spawn(fun2) gevent.joinall([t1, t2])
-
什么是异步非阻塞? (2分)
# 异步 : 一个程序在执行中调用了另一个 但是不等待这个任务完毕 就继续执行 start
-
什么是死锁?如何避免?(2分)
锁套锁导致无法解锁,避免锁的嵌套
-
程序从flag a执行到falg b的时间大致是多少秒?(2分)
import threading import time def _wait(): time.sleep(60) # flag a t = threading.Thread(target=_wait) t.setDeamon(False) t.start() # flag b 60
-
程序从flag a执行到falg b的时间大致是多少秒?(2分)
import threading import time def _wait(): time.sleep(60) # flag a t = threading.Thread(target=_wait) t.setDeamon(True) t.start() # flag b 0.01秒
-
程序从flag a执行到falg b的时间大致是多少秒?(2分)
import threading import time def _wait(): time.sleep(60) # flag a t = threading.Thread(target=_wait) t.start() t.join() # flag b 5秒
-
读程序,请确认执行到最后number是否一定为0(2分)
import threading loop = int(1E7) def _add(loop:int = 1): global number for _ in range(loop): number += 1 def _sub(loop:int = 1): global number for _ in range(loop): number -= 1 number = 0 ta = threading.Thread(target=_add,args=(loop,)) ts = threading.Thread(target=_sub,args=(loop,)) ta.start() ta.join() ts.start() ts.join() 是
-
读程序,请确认执行到最后number是否一定为0(2分)
import threading loop = int(1E7) def _add(loop:int = 1): global number for _ in range(loop): number += 1 def _sub(loop:int = 1): global number for _ in range(loop): number -= 1 number = 0 ta = threading.Thread(target=_add,args=(loop,)) ts = threading.Thread(target=_sub,args=(loop,)) ta.start() ts.start() ta.join() ts.join() 否
-
MySQL常见数据库引擎及区别?(3分)
# 存储引擎的种类 # innodb : 索引+数据 表结构 数据的持久化存储 # 事务 :一致性 n条语句的执行状态是一致的 # begin; # 开启事务 # select id from innot where id =1 for update; # update innot set id = 2 where id = 1; # commit; # 提交事务 解锁被锁住的数据,让他们能够被修改 # 行级锁 :只对涉及到修改的行加锁,利于并发的修改,但是对于一次性大量修改效率低下 # 表级锁 :一次性加一把锁就锁住了整张表,不利于并发的修改,但是加锁速度比行锁的效率要高 # 外键约束 :被约束表中的数据不能随意的修改/删除 约束字段据要根据被约束表来使用数据 # myisam : 索引 数据 表结构 数据的持久化存储 # 表级锁 # memory : 表结构 # 数据断电消失
-
简述事务及其特性? (3分)
# 事务 :一致性 n条语句的执行状态是一致的 # begin; # 开启事务 # select id from innot where id =1 for update; # update innot set id = 2 where id = 1; # commit; # 提交事务 解锁被锁住的数据,让他们能够被修改
-
事务的隔离级别?(2分)
第一种隔离级别:Read uncommitted(读未提交) 如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。这样就避免了更新丢失,却可能出现脏读,也就是说事务B读取到了事务A未提交的数据 解决了更新丢失,但还是可能会出现脏读 第二种隔离级别:Read committed(读提交) 如果是一个读事务(线程),则允许其他事务读写,如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。 解决了更新丢失和脏读问题 第三种隔离级别:Repeatable read(可重复读取) 可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。 解决了更新丢失、脏读、不可重复读、但是还会出现幻读 第四种隔离级别:Serializable(可序化) 提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读 解决了更新丢失、脏读、不可重复读、幻读(虚读) ———————————————— 版权声明:本文为CSDN博主「zhouym_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/zhouym_/article/details/90381606
-
char和varchar的区别?(2分)
char和varchar都是定义字符串 但是varchar定义的是自动调节开辟的空间,用不了可以回收
-
mysql中varchar与char的区别以及varchar(50)中的50代表的含义。(2分)
50表示最大可以存储的长度
-
MySQL中delete和truncate的区别?(2分)
delete表示删除数据,但是还是用删除前的id truncate也表示删除,但是删除以后重新进行id排序
-
where子句中有a,b,c三个查询条件, 创建一个组合索引abc(a,b,c),以下哪种会命中索引(3分)
(a)1 (b) (c) (a,b)1 (b,c) (a,c)1 (a,b,c)1
-
组合索引遵循什么原则才能命中索引?(2分)
开头从左边的索引开头
-
列举MySQL常见的函数? (3分)
# count # max # min # avg # sum
-
MySQL数据库 导入、导出命令有哪些? (2分)
1.导入 语法格式:mysql -h ip -u userName -p dbName < sqlFilePath (最后没有分号) -h : 数据库所在的主机。如果是本机,可以使用localhost,或者省略此项; -u : 连接数据库用户名。 -p : 连接数据库密码。出于安全考虑,一般不在-p之后直接写出明文的密码。整个命令回车之后,数据库会要求输入密码,那个时候再输入密码将以**的形式显示出来。有一定的保护作用。 dbName : 要使用的具体的某个数据库。这个不是必须的,如果sql脚本中没有使用“use dbName”选择数据库,则此处必须制定数据库;如果使用了”use dbName”,则可以省略。 sqlFilePath : sql脚本的路径。如我将sql脚本放在了D盘,我的sql脚本的名字是”test_sql.sql”。则路径为”D:\test_sql.sql”。 2.命令行导出 导出某个数据库: mysqldump -u root -p dbName > sqlFilePath 导出多个数据库: mysqldump -u root -p –add-drop-database –databases dbName1 dbName2… > sqlFilePath –add-drop-database : 该选项表示在创建数据库的时候先执行删除数据库操作 –database : 该选项后面跟着要导出的多个数据库,以空格分隔 导出某个数据库的某个表: mysqldump -u root -p dbName tableName > sqlFilePath 只导出数据库结构,不带数据: mysqldump -u root -p -d dbName > sqlFilePath -d : 只备份结构,不备份数据。也可以使用”–no-data”代替”-d”,效果一样。
-
什么是SQL注入?(2分)
就是将写好的表或数据导入到mysql
-
简述left join和inner join的区别?(2分)
左连接:以左边的表为主要核心,没有的数据丢掉 全连接:数据全部保存
-
SQL语句中having的作用?(2分)
筛选出符合条件的数据
-
MySQL数据库中varchar和text最多能存储多少个字符?(2分)
一个TEXT列,最大长度为65535(2^16-1)个字符 varchar(n) 表示n个字符,无论汉字和英文,MySql都能存入 n 个字符,仅实际字节长度有所区别。
MySQL的索引方式有几种?(3分)
什么时候索引会失效?(有索引但无法命中索引)(3分)
数据库优化方案?(3分)
什么是MySQL慢日志?(2分)
-
设计表,关系如下: 教师, 班级, 学生, 科室。(4分)
科室与教师为一对多关系, 教师与班级为多对多关系, 班级与学生为一对多关系, 科室中需体现层级关系。1. 写出各张表的逻辑字段 2. 根据上述关系表 a.查询教师id=1的学生数 b.查询科室id=3的下级部门数 c.查询所带学生最多的教师的id
有staff表,字段为主键Sid,姓名Sname,性别Sex(值为"男"或"女"),课程表Course,字段为主键Cid,课程名称Cname,关系表SC_Relation,字段为Student表主键Sid和Course表主键Cid,组成联合主键,请用SQL查询语句写出查询所有选"计算机"课程的男士的姓名。(3分)
-
根据表关系写SQL语句(10分)
- 查询所有同学的学号、姓名、选课数、总成绩;
- 查询姓“李”的老师的个数;
- 查询平均成绩大于60分的同学的学号和平均成绩;
- 查询有课程成绩小于60分的同学的学号、姓名
- 删除学习“叶平”老师课的score表记录;
- 查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分;
- 查询每门课程被选修的学生数;
- 查询出只选修了一门课程的全部学生的学号和姓名;
- 查询选修“杨艳”老师所授课程的学生中,成绩最高的学生姓名及其成绩;
- 查询两门以上不及格课程的同学的学号及其平均成绩;
第二部分 补充题
什么是IO多路复用?
async/await关键字的作用?
MySQL的执行计划的作用?
简述MySQL触发器、函数、视图、存储过程?
-
数据库中有表:t_tade_date
id tade_date 1 2018-1-2 2 2018-1-26 3 2018-2-8 4 2018-5-6 ... 输出每个月最后一天的ID