python面试题 -- 网编并发

Python面试重点(进阶篇)

注意:只有必答题部分计算分值,补充题不计算分值。

第一部分 必答题

  1. 简述 OSI 7层模型及其作用?(2分)

    # 应用层:文件传输,文件管理,电子邮件的信息处理
    # 表示层:确保一个系统的应用层发送的消息可以被另一个系统的应用层读取,编码转换,数据解析,管理数据的解密和加密
    # 会话层:验证访问和会话管理
    # 传输层:为应用程序之间提供端对端的逻辑通信。
    # 网络层:选择合适的网间路由完成两个计算机之间的多个数据链路,通过路由协议和地址解析协议(ARP)。IP,RIP(路由信息协议),OSPF(最短路径优先协议)
    # 数据链路层:在物理层提供的比特流的基础上,建立相邻节点之间的数据链路,不可靠的物理介质提供可靠传输 ppp协议
    # 物理层:规定通信设备,通信链路的特性
  2. 简述 TCP三次握手、四次回收的流程。(3分)

    # 第一次握手:客户端首先向服务端发起连接,这时TCP头部中的SYN标识位值为1,然后选定一个初始序号seq=x(一般是随机的),消息发送后,A进入SYN_SENT状态,SYN=1的报文段不能携带数据,但要消耗一个序号。
    # 第二次握手:服务端收到客户端的连接请求后,同意建立连接,向A发送确认数据,这时TCP头部中的SYN和ACK标识位值均为1,确认序号为ack=x+1,然后选定自己的初始序号seq=y(一般是随机的),确认消息发送后,服务端进入SYN_RCVD状态,与连接消息一样,这条消息也不能携带数据,同时消耗一个序号。
    # 第三次握手:客户端收到服务端的确认消息后,需要给服务端回复确认数据,这时TCP头部中的ACK标识位值为1,确认序号是ack=y+1,自己的序号在连接请求的序号上加1,也就是seq=x+1,此时客户端进入ESTABLISHED状态,当服务端收到客户端的确认回复后,服务端也进入ESTABLISHED状态,至此TCP成功建立连接,客户端和服务端之间就可以通过这个连接互相发送数据了。

    #第一次挥手:客户端首先向服务端发送断开连接消息,这时TCP头部中的FIN标识位值为1,序号是seq=m,m为客户端前面正常发送数据最后一个字节序号加1得到的,消息发送后客户端进入FNI_WAIT_1状态,FIN=1的报文段不能携带数据,但要消耗一个序号。
    # 第二次挥手:服务端收到客户端的断开连接请求需要发出确认消息,这时TCP头部中的ACK标识位值为1,确认号为ack=m+1,而自己的序号为seq=n,n为服务端前面正常发送数据最后一个字节序号加1得到的,然后服务端进入CLOSE_WAIT状态,此时就关闭了客户端到服务端的连接,客户端无法再给服务端发数据,但是服务端仍然可以给客户端发数据,同时服务端端通知上方应用层,处理完成后被动关闭连接。然后客户端收到服务端的确认信息后,就进入了FIN_WAIT_2状态。
    # 第三次挥手:服务端端应用层处理完数据后,通知关闭连接,服务端向客户端发送关闭连接的消息,这时TCP头部中的FIN和ACK标识位值均为1,确认号ack=m+1,自己的序号为seq=k,消息发送后服务端进入LAST_ACK状态。
    # 第四次挥手:客户端收到服务端的断开连接的消息后,需要发送确认消息,这是这时TCP头部中的ACK标识位值为1,确认号ack=k+1,序号为m+1(因为客户端向服务端发送断开连接的消息时消耗了一个消息号),然后客户端进入TIME_WAIT状态,若等待时间经过2MSL后,没有收到服务端的重传请求,则表明服务端收到了自己的确认,客户端进入CLOSED状态,服务端收到客户端的确认消息后则直接进入CLOSED状态。至此TCP成功断开连接。
  3. TCP和UDP的区别?(3分)

    #TCP协议 上传下载\发邮件、可靠、面向连接、速度慢、能传递的数据长度不限、流式传输、全双工(连接上之后,server端和client端可以相互通信)
    # UDP协议 即时通讯工具、不可靠、面向数据报、速度快、能传递的数据长度有限、不管对方在不在,直接发送、应用:短消息类、在线观看视频不占连接、随时可以收发消息
  4. 什么是黏包?(2分)

    # 当多条消息发送时接收变成了一条或者出现接收不准确的情况
  5. 什么 B/S 和 C/S 架构?(2分)

    # B/S:B浏览器,S服务端,在浏览器输入地址就可以直接使用的一种网络架构,浏览器充当客户端
    # C/S:C客户端,S服务端,需要安装客户端使用的网络架构
  6. 请实现一个简单的socket编程(客户端和服务端可以进行收发消息)(3分)

    server端:

    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("你好".encode("utf-8"))      
    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()          
  7. 简述进程、线程、协程的区别?(3分)

    # 进程是计算机中资源分配的最小单位
    # 线程是计算机中能被cpu调度的最小单位
    # 协程又称为微线程,是基于代码人为创造的,而进程和线程是计算机中真实存在的
    # 一个进程中可以有多个线程,一个线程中可以有多个协程
    # 计算密集型用多进程
    # IO密集型用多线程/协程+IO操作
    # 单纯的协程是没办法提高并发的,只是代码之间的来回切换,加上IO自动切换才有意义,应用场景,有IO操作用协程
  8. 什么是GIL锁?(2分)

    #全局解释器锁,为了同一时刻保证一个进程中只有一个线程可以被cpu调度
  9. 进程之间如何进行通信?(2分)

    # 默认进程之间无法进行资源共享,如果主要想要通讯可以基于:文件/网络/Queue.
  10. Python如何使用线程池、进程池?(2分)

    # 进程池:调用ProcessPoolExecutor模块创建进程池,通过submit执行进程
    # 线程池:调用ThreadPoolExecutor模块创建进程池,通过submit执行进程
  11. 请通过yield关键字实现一个协程? (2分)

    # 
  12. 什么是异步非阻塞? (2分)

    #异步: 一个程序在执行中调用了另一个 但是不等待这个任务完毕 就继续执行
    #非阻塞:cpu工作
  13. 什么是死锁?如何避免?(2分)

    # 由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行
    # 避免lock锁两次(嵌套锁),避免RLock 多个锁交叉使用
  14. 程序从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
    # 60s
  15. 程序从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
    # 0s
  16. 程序从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
    # 60s
  17. 读程序,请确认执行到最后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()
    # 0
  18. 读程序,请确认执行到最后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()
    # 不一定为0
  19. MySQL常见数据库引擎及区别?(3分)

    # MySQL常见的三种存储引擎为InnoDB、MyISAM和MEMORY
    # 区别:
    # 1、事务安全:InnoDB支持事务安全,MyISAM和MEMORY两个不支持。
    # 2、存储限制:InnoDB有64TB的存储限制,MyISAM和MEMORY要是具体情况而定。
    # 3、空间使用:InnoDB对空间使用程度较高,MyISAM和MEMORY对空间使用程度较低。
    # 4、内存使用:InnoDB和MEMORY对内存使用程度较高,MyISAM对内存使用程度较低。
    # 5、插入数据的速度:InnoDB插入数据的速度较低,MyISAM和MEMORY插入数据的速度较高。
    # 6、对外键的支持:InnoDB对外键支持情况较好,MyISAM和MEMORY两个不支持外键。
  20. 简述事务及其特性? (3分)

    # 事务是访问并可能更新数据库中各种数据项的一个程序执行单元
    # 特性:原子性、一致性、隔离性、持续性
    # 原子性:一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
    # 一致性:事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
    # 隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
    # 持久性:持续性也称永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
  21. 事务的隔离级别?(2分)

    # 读未提交、不可重复读、可重复读、串行化
  22. char和varchar的区别?(2分)

    # char 定长(固定长度,不够补空字符串),节省时间,浪费空间   varchar  变长(长度不固定),节省空间,浪费时间
  23. mysql中varchar与char的区别以及varchar(50)中的50代表的含义。(2分)

    # # char 定长(固定长度,不够补空字符串),节省时间,浪费空间   varchar  变长(长度不固定),节省空间,浪费时间
    # 50指长度为50
  24. MySQL中delete和truncate的区别?(2分)

    # delete可以条件删除数据,而truncate只能删除表的所有数据
    # delete效率低于truncate,delete是一行一行地删除,truncate会重建表结构
    # truncate是DDL语句,需要drop权限,因此会隐式提交,不能够rollback;delete是DML语句,可以使用rollback回滚。
    # 触发器:truncate 不能触发任何Delete触发器;而delete可以触发delete触发器
  25. where子句中有a,b,c三个查询条件, 创建一个组合索引abc(a,b,c),以下哪种会命中索引(3分)

    (a)
    (b)
    (c)
    (a,b)
    (b,c)
    (a,c)
    (a,b,c)
    # (a),(a,b),(a,c),(a,b,c)
  26. 组合索引遵循什么原则才能命中索引?(2分)

    #最左前缀原则
  27. 列举MySQL常见的函数? (3分)

    # concat:拼接,count 计数 max 最大值 min 最小值 avg 平均值 sum 求和
  28. MySQL数据库 导入、导出命令有哪些? (2分)

    # 导出表结构+数据:mysqldump -u用户名 -p 数据库名 > 数据库名.sql
    # 导出表结构:mysqldump -u用户名 -p -d 数据库名 > 数据库名.sql
    # 导出全部数据库:mysqldump -uroot -p --all-databases   > alldb.sql

    # 导入数据库:mysql -u用户名 -p 数据库名 < 数据库名.sql
  29. 什么是SQL注入?(2分)

    # SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息
  30. 简述left join和inner join的区别?(2分)

    # left join:拼接两张表,数据多的在左边
    # inner join:对两张表的相同部分进行拼接
  31. SQL语句中having的作用?(2分)

    # 过滤
  32. MySQL数据库中varchar和text最多能存储多少个字符?(2分)

    # varchar:21839
    # text:65535
  33. MySQL的索引方式有几种?(3分)

    # fulltext:全文索引
    # hash
    # btree
    # rtree
  34. 什么时候索引会失效?(有索引但无法命中索引)(3分)

    # 1、如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
    # 2、对于多列索引,不是使用的第一部分(第一个),则不会使用索引
    # 3、like查询是以%开头
    # 4、如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
    # 5、如果mysql估计使用全表扫描要比使用索引快,则不使用索引
  35. 数据库优化方案?(3分)

    # SQL语句中IN包含的值不应过多
    # SELECT语句务必指明字段名称
    # 当只需要一条数据的时候,使用limit 1
    # 如果排序字段没有用到索引,就尽量少排序
    # 如果限制条件中其他字段没有索引,尽量少用or
    # 分段查询
    # 避免在where子句中对字段进行null值判断
    # 避免在where子句中对字段进行表达式操作
    # 对于联合索引来说,要遵守最左前缀法则
  36. 什么是MySQL慢日志?(2分)

    # mysql的慢查询日志是msyql提供的一种日志记录,它用来记录在msyql中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的sql,则会被记录到慢查询日志中。
  37. 设计表,关系如下: 教师, 班级, 学生, 科室。(4分) 科室与教师为一对多关系, 教师与班级为多对多关系, 班级与学生为一对多关系, 科室中需体现层级关系。

    1.  写出各张表的逻辑字段
    'create table department(id int primary key,dname char(12),pid int);'

    'create table teacher(id int primary key,tname char(16),did int,foreign key(did) references department(id));'

    'create table class(id int primary key,cname char(12));'

    'create table teach_cls(id int,cid int,tid int,foreign key(cid) references class(id),foreign key(tid) references teacher(id));'

    'create table student(id int primary key,sname char(16),cid int,foreign key(cid) references class(id));'

    insert into department VALUES(1,'校长室',0),(2,'教学处',1),(3,'办公室1',2),(4,'办公室2',2);
    insert into teacher VALUES(1,'王老师',1),(2,'张老师',2),(3,'孙老师',3),(4,'李老师',3),(5,'伊老师',4);
    insert into class VALUES(1,'1班'),(2,'2班'),(3,'3班');
    insert into teach_cls VALUES(1, 3, 1), (2, 3, 2), (3, 3, 3), (4, 2, 1), (5, 2, 2), (6, 1, 3);
    insert into student VALUES(1,'赵雷',1),(2,'钱电',1),(3,'孙风',1),(4,'李云',2),(5,'周梅',2),(6,'吴兰',3),(7,'郑竹',3);
    2.  根据上述关系表
       a.查询教师id=1的学生数
    # select count(cid) from student where cid in (select cid from teach_cls where tid=1);
       b.查询科室id=3的下级部门数
    # select count(*) from department where pid = 2;
       c.查询所带学生最多的教师的id
    #

猜你喜欢

转载自www.cnblogs.com/sunyongchao/p/12371411.html