zoukankan      html  css  js  c++  java
  • python面试题----2

    Python面试重点(进阶篇)

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

    第一部分 必答题

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

      物理层:主要是基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0
      
      数据链路层:定义了电信号的分组方式
      
      网路层:引入一套新的地址用来区分不同的广播域/子网,这套地址即网络地址
      
      传输层:建立端口到端口的通信
      
      会话层:建立客户端与服务端连接
      
      表示层:对来自应用层的命令和数据进行解释,按照一定格式传给会话层。如编码、数据格式转换、加密解密、压缩解压
      应用层:规定应用程序的数据格式
      
    2. 简述 TCP三次握手、四次回收的流程。(3分)

      三次握手:
          第一次握手
       	1:客户端先向服务端发起一次询问建立连接的请求,并随机生成一个值作为标识
          第二次握手
       	2:服务端向客户端先回应第一个标识,再重新发一个确认标识
          第三次握手
       	3:客户端确认标识,建立连接,开始传输数据
      
      四次挥手 ---> 断开连接
       第一次挥手
          	客户端向服务端发起请求断开连接的请求
       第二次挥手
          	服务端向客户端确认请求
       第三次挥手
          	服务端向客户端发起断开连接请求
       第四次挥手
          	客户端向服务端确认断开请求
      
    3. TCP和UDP的区别?(3分)

      TCP/UDP区别
       TCP协议是面向连接,保证高可靠性传输层协议
       UDP:数据丢失,无秩序的传输层协议(qq基于udp协议)
      
    4. 什么是黏包?(2分)

      在获取数据时,接收方不知道数据长度,将多个数据包一次接受,造成数据黏在一起
      
    5. 什么 B/S 和 C/S 架构?(2分)

      c/s架构,就是client(客户端)与server(服务端)即:客户端与服务端的架构。
      
      b/s架构,就是brosver(浏览器端)与sever(服务端)即:浏览器端与服务端架构
      
      优点:统一了所有应用程序的入口、方便、轻量级
      
    6. 请实现一个简单的socket编程(客户端和服务端可以进行收发消息)(3分)

      服务端
      import socket
      sk = socket.socket()
      sk.bind(('127.0.0.1',6666))
      sk.listen()
      conn,addr=sk.accept()
      ma = conn.recv(1024).decode('utf-8')
      print(ma)
      sonn.close()
      sk.close()
      
      客户端
      import socket
      sk = socket.socket()
      sk.connect(('127.0.0.1',6666))
      mc = sk.send('这是客户端'.encode('utf-8'))
      sk.close()
      
    7. 简述进程、线程、协程的区别?(3分)

      进程是计算机分配资源的最小单位,线程是被CPU调用的最小单位,协程又称为微线程,是基于代码人为创造的
      ,而进程和线程是计算机中真实存在的,一个进程中可以有多个线程,一个线程可以创建多个协程;
      
      ​		在python中由于有GIL锁,所以在同一时刻的同一进程中只能有一个线程被CPU调用,在python开发中
      计算密集型应用用多进程
      IO密集型用多线程
      
      ​	单纯的协程是没有办法并发,只是代码之间的来回切换,加上io自动切换才有意义,有 io操作时才用协程
      
      ​	进程之间不能资源共享,线程间的资源是 共享的,协程需要导入第三方库,需要加补丁
      
    8. 什么是GIL锁?(2分)

      全局解释器锁
      同一时刻保证一个进程中只有一个线程可以被cpu调度,所以在使用Python开发时要注意:
      计算密集型,用多进程.
      IO密集型,用多线程.
      
    9. 进程之间如何进行通信?(2分)

      进程间的通信  IPC  队列   生产者消费者模型
      进程之间通信 IPC
      Inter Process Communication
      from multiprocessing import Queue,Process
      
      def son(q):
          print(q.get())
      
      if __name__ == '__main__':
          q = Queue()
          p = Process(target=son,args=(q,))
          p.start()
          q.put(123)
      在进程之间维护数据的安全 -- 进程安全
      队列是进程安全的(进程队列保证了进程的数据安全)
      队列都是先进先出的
      队列是基于文件 + 锁实现的
      队列一共提供两个方法:get put
      
      q = Queue()
      q.put({1,2,3})
      num = q.get()  # get是一个同步阻塞方法,会阻塞直到数据来
      print(num)
      
      q = Queue(2)
      q.put({1,2,3})
      q.put({1,2,3})
      q.put({1,2,3})  # put是一个同步阻塞方法,会阻塞直到队列不满
      import queue
      q = Queue(2)
      try:
          for i in range(4):
              q.put_nowait(i)  # put_nowait 同步非阻塞方法
      except queue.Full:
          print(i)
      
      q2 = Queue(2)
      try:
          print(q2.get_nowait())
      except queue.Empty:pass
      
      q = Queue(5)
      ret = q.qsize()  # 查看当前队列有多少值
      print(q.empty())
      print(q.full())
      
      生产者消费者模型
      
      队列Queue = 管道Pipe + 锁
      Pipe  基于文件实现的(socket+pickle)  =  数据不安全
      Queue 基于文件(socket+pickle)+锁(lock)实现的  =  数据安全
           基于pipe+锁(lock)实现的
      
      IPC:
          内置的模块实现的机制 :队列管道
          第三方工具 : redis rabbitMQ memcache
      
    10. Python如何使用线程池、进程池?(2分)

    作用:
      保证程序中最多可以创建的线程(进程)个数,防止无节制的创建线程(进程),导致性能降低
    线程池
    例一:
    import time
    from concurrent.futures import ThreadPoolExecutor
    def task(n1, n2):
         time.sleep(2)
         print('任务')
    pool = ThreadPoolExecutor(10)# 创建线程池
    for i in range(100):
        pool.submit(task, i, 1)
    print('END')
    pool.shutdown(True)# 等线程池中的任务执行完毕之后,再继续往下走
    print('其他操作,依赖线程池执行的结果')
    
    例二:
    import time
    from concurrent.futures import ThreadPoolExecutor
    def task(n1, n2):
        time.sleep(2)
        print('任务')
        return n1+n2
    pool = ThreadPoolExecutor(10)# 创建线程池
    future_list = []
    for i in range(20):
        fu = pool.submit(task, i, 1)
        future_list.append(fu)
        pool.shutdown(True)
    for fu in future_list:
        print(fu.result())
    
    进程池
    例:
    import time
    from concurrent.futures import ProcessPoolExecutor
    def task(n1, n2):
        time.sleep(2)
        print('任务')
    if __name__ == '__main__':
        pool = ProcessPoolExecutor(10) # 创建进程池
        for i in range(20):
            pool.submit(task, i, 1)
            print('END')
    
    1. 请通过yield关键字实现一个协程? (2分)

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

      非阻塞:不等待
      即:遇到IO阻塞不等待(setblooking=False),(可能会报错->捕捉异常)
              - sk=socket.socket()
              - sk.setblooking(False)
      异步:回调,当达到某个指定的状态之后,自动调用特定函数
      
      
    3. 什么是死锁?如何避免?(2分)

      当两个线程相互等待对方释放资源时,就会发生死锁。
      避免:
      	1.避免多次锁定
      	2.具有相同的加锁顺序
      	3.使用定时锁
      	4.死锁检测
      
    4. 程序从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
      
    5. 程序从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 不用等待
      
    6. 程序从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  60
      
    7. 读程序,请确认执行到最后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
      
    8. 读程序,请确认执行到最后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() 不是1
      
    9. MySQL常见数据库引擎及区别?(3分)

      InnoDB 
      支持事务
      支持表锁、行锁(for update)
      表锁:select * from tb for update
      行锁:select id,name from tb where id=2 for update
      
      myisam
      查询速度快
      全文索引
      支持表锁
      表锁:select * from tb for update
      
      NDB
      高可用、 高性能、高可扩展性的数据库集群系统
      
      Memory 
      默认使用的是哈希索引
      
    10. 简述事务及其特性? (3分)

      事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。
      
      事务的特性: 
      原子性: 确保工作单元内的所有操作都成功完成,否则事务将被中止在故障点,和以前的操作将回滚到以前的状态。
      一致性: 确保数据库正确地改变状态后,成功提交的事务。
      隔离性: 使事务操作彼此独立的和透明的。
      持久性: 确保提交的事务的结果或效果的系统出现故障的情况下仍然存在。
      
      
    11. 事务的隔离级别?(2分)

      读未提交(read uncommitted)
      一个事务还没提交时,它做的变更就能被别的事务看到
      
      读提交(read committed)
      一个事务提交之后,它做的变更才会被其他事务看到
      
      可重复读(repeatable read)
      一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的
      
      串行化(serializable )
      顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行
      
    12. char和varchar的区别?(2分)

      varchar与char的区别char是一种固定长度的类型,varchar则是一种可变长度的类型
      char是定长 ,用空间换时间
      varchar,是可变长度,用时间换空间
      
    13. mysql中varchar与char的区别以及varchar(50)中的50代表的含义。(2分)

      varchar(50)表示最大长度为50字节
      char(50)表示一个字符占50字节
      
    14. MySQL中delete和truncate的区别?(2分)

      delete 是删除一条数据,truncate是将这个表的所有数据都删除
      
    15. where子句中有a,b,c三个查询条件, 创建一个组合索引abc(a,b,c),以下哪种会命中索引(3分)

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

      -  1.只有对创建了索引的列进行条件筛选的时候效率才能提高
      
      -  2.索引对应的列做条件不能参与运算、不能使用函数
      
      -  3.当某一列的区分度非常小(重复率高),不适合创建索引
      
      -  4.当范围作为条件的时候,查询结果的范围越大越慢,越小越快
      
      -  5.like关键字 : 如果使用%/_开头都无法命中索引
      
      -  6.多个条件 : 如果只有一部分创建了索引,条件用and相连,那么可以提高查询效率,如果用or相连,不能提高查询效率
      
    17. 列举MySQL常见的函数? (3分)

      聚合函数
      max/sum/min/avg
      
      时间格式化
      date_format
      
      字符串拼接
      concat(当拼接了null,则返回null)
      
      截取字符串
      substring
      
      返回字节个数
      length
      
      
    18. MySQL数据库 导入、导出命令有哪些? (2分)

      导出sql文件可以使用mysqldump。
      
      主要有如下几种操作:
      1.导出整个数据库(包括数据库中的数据):
      	mysqldump -u username -ppassword dbname > dbname.sql ;   
      2.导出数据库中的数据表(包括数据表中的数据):
      	mysqldump -u username -ppassword dbname tablename > tablename.sql;
      3.导出数据库结构(不包括数据,只有创建数据表语句):
      	mysqldump -u username -ppassword -d dbname > dbname.sql;
      4.导出数据库中数据表的表结构(不包括数据,只有创建数据表语句):
      	mysqldump -u username -ppassword -d dbname tablename > tablename.sql。   
      导出:mysqldump --default-character-set=utf8 -u root -p news > news.sql
      
      导入
       连接数据库时:
      	 source sql文件路径
       未连接数据库
       	 mysql -h ip -u userName -p dbName < sqlFilePath (最后没有分号) 
      
       	 导入:mysql --default-character-set=utf8 -u root -p news<news.sql 
      
    19. 什么是SQL注入?(2分)

      sql注入是一种将sql代码添加到输入参数中,传递到sql服务器解析并执行的一种攻击手法
      
    20. 简述left join和inner join的区别?(2分)

      left join 是左连接
      inner join是内连接
      
    21. SQL语句中having的作用?(2分)

      having过滤出符合条件的内容
      
    22. MySQL数据库中varchar和text最多能存储多少个字符?(2分)

      varchar(n) 表示n个字符,无论汉字和英文,MySql都能存入 n 个字符,仅实际字节长度有所区别
      
      在UTF8状态下text: 65535/3=21845个汉字,约20000,存储空间占用:65535/1024=64K的数据;
      在UTF8状态下的varchar,最大只能到 (65535 - 2) / 3 = 21844个汉字,英文也为 21844个字符串
      
    23. MySQL的索引方式有几种?(3分)

      单列
      功能
         普通索引:加速查找
         唯一索引:加速查找 + 约束:不能重复(只能有一个空,不然就重复了)
         主键(primay key):加速查找 + 约束:不能重复 +  不能为空
      多列
        联合索引(多个列创建索引)-----> 相当于单列的普通索引
        联合唯一索引            -----> 相当于单列的唯一索引
        ps:联合索引的特点:遵循最左前缀的规则
      其他词语:
      ·· - 索引合并,利用多个单例索引查询;(例如在数据库查用户名和密码,分别给用户名和密码建立索引)
         - 覆盖索引,在索引表中就能将想要的数据查询到;
      
    24. 什么时候索引会失效?(有索引但无法命中索引)(3分)

      
      
    25. 数据库优化方案?(3分)

      
      1、创建数据表时把固定长度的放在前面()
      2、将固定数据放入内存: 例如:choice字段 (django中有用到,数字1、2、3…… 对应相应内容)
      3、char 和 varchar 的区别(char可变, varchar不可变 )
        
      4、联合索引遵循最左前缀(从最左侧开始检索)
      5、避免使用 select * 
      6、读写分离
          - 实现:两台服务器同步数据
          - 利用数据库的主从分离:主,用于删除、修改、更新;从,用于查;
      读写分离:利用数据库的主从进行分离:主,用于删除、修改更新;从,用于查
      7、分库
          - 当数据库中的表太多,将某些表分到不同的数据库,例如:1W张表时
          - 代价:连表查询
      8、分表
          - 水平分表:将某些列拆分到另外一张表,例如:博客+博客详情
          - 垂直分表:讲些历史信息分到另外一张表中,例如:支付宝账单
      
      9、加缓存
          - 利用redis、memcache (常用数据放到缓存里,提高取数据速度)
      
      如果只想获取一条数据
           - select * from tb where name=‘alex’ limit 1
      
    26. 什么是MySQL慢日志?(2分)

      慢日志查询的主要功能就是,记录sql语句中超过设定的时间阈值的查询语句。例如,一条查询sql语句,我们设置的阈值为1s,当这条查询语句的执行时间超过了1s,则将被写入到慢查询配置的日志中.
      慢查询主要是为了我们做sql语句的优化功能.
      
      修改配置文件
      slow_query_log = OFF                            是否开启慢日志记录
      long_query_time = 2                              时间限制,超过此时间,则记录
      slow_query_log_file = /usr/slow.log        日志文件
      log_queries_not_using_indexes = OFF     为使用索引的搜索是否记录
      
      下面是开启
      slow_query_log = ON
      long_query_time = 2   
      log_queries_not_using_indexes = OFF 
      log_queries_not_using_indexes = ON
      
      注:查看当前配置信息:
             show variables like '%query%'
           修改当前配置:
          set global 变量名 = 值
      
    27. 设计表,关系如下: 教师, 班级, 学生, 科室。(4分) 科室与教师为一对多关系, 教师与班级为多对多关系, 班级与学生为一对多关系, 科室中需体现层级关系。

      1.  写出各张表的逻辑字段
      2.  根据上述关系表
          a.查询教师id=1的学生数
          b.查询科室id=3的下级部门数
          c.查询所带学生最多的教师的id
      
    28. 有staff表,字段为主键Sid,姓名Sname,性别Sex(值为"男"或"女"),课程表Course,字段为主键Cid,课程名称Cname,关系表SC_Relation,字段为Student表主键Sid和Course表主键Cid,组成联合主键,请用SQL查询语句写出查询所有选"计算机"课程的男士的姓名。(3分)

    29. 根据表关系写SQL语句(10分)

      • 查询所有同学的学号、姓名、选课数、总成绩;
      • 查询姓“李”的老师的个数;
      • 查询平均成绩大于60分的同学的学号和平均成绩;
      • 查询有课程成绩小于60分的同学的学号、姓名
      • 删除学习“叶平”老师课的score表记录;
      • 查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分;
      • 查询每门课程被选修的学生数;
      • 查询出只选修了一门课程的全部学生的学号和姓名;
      • 查询选修“杨艳”老师所授课程的学生中,成绩最高的学生姓名及其成绩;
      • 查询两门以上不及格课程的同学的学号及其平均成绩;

    第二部分 补充题

    1. 什么是IO多路复用?

    2. async/await关键字的作用?

    3. MySQL的执行计划的作用?

    4. 简述MySQL触发器、函数、视图、存储过程?

    5. 数据库中有表:t_tade_date

      id		tade_date
      1		2018-1-2
      2		2018-1-26
      3		2018-2-8
      4		2018-5-6
      ...
      输出每个月最后一天的ID
      
  • 相关阅读:
    SDN第七次上机作业
    SDN第六次上机作业
    SDN第五次上机实验
    SDN阅读作业(二)
    软件评测——腾讯音视频
    SDN上机第四次作业
    SDN上机第三次作业
    SDN阅读作业
    SpringBoot整合Swagger2
    JavaWeb项目前后端分离
  • 原文地址:https://www.cnblogs.com/python111/p/12371046.html
Copyright © 2011-2022 走看看