Python面试题整理

吃可爱长大的小学妹 提交于 2021-01-03 08:31:24

1.  什么情况下使用Python语言开发比较好?/你对Python怎么看?/。。。

  回答思路:

  时间线:

  1991年,第一个稳定的Python版本;

  2000年,Python2.7稳定版本发布;

  2008年,Python3发布;

  2020年,Python2不再维护;

 

  空间线:

  Python设计哲学;

  Python2、3特性;

  和其他编程语言(如c++)对比;

  语言选型考虑因素;

 

  思路串联:设计哲学(Python本质特性)-> 如何选型(正面回答,取其精华) -> 埋下一个问题引子

 

  示例答案:Python自1991年Rossum编写发布出第一个版本以来,便一直遵循着其设计哲学”简单、明确、优雅“,设计哲学的根本出发点就决定了Python这门语言的编程开发的易用性和工作高效性,同样的业务需求实现,可能传统编程语言C++程序猿需要1周工期,而Python程序猿很有可能三天不到就能完成,而且潜在隐藏的问题会少很多,因为Python本身目前有非常庞大的开源第三方库,同时封装了很多复杂的语言底层操作如内存分配与释放,指针的相关操作等;

  在具体的项目实践过程中,开发语言的选型需要考虑到几个方面:项目业务本身的特点适合哪种语言、公司历史的技术栈和人员技术储备倾向于哪种语言、选型的语言当前领域内的生态体系和发展前景(比如是否不在维护);如果项目非计算密集型项目,其中对于算法性能等要求不是非常非常高,相对而言是业务功能和流程逻辑较为复杂,此时Python语言就天然具备很大的优势,碰到其中少部分算法等计算性能瓶颈的地方可以用c++等语言重写,然后Python调用,这样可以兼顾Python开发低成本和C++高性能两方面的有点;

  具体选用Python后,新项目推荐使用python3,2008年Python3发布后,十几年来Python3生态圈三方库已经非常完备和齐全,而官方已宣布Python2在2020年将不再维护,另外Python3本身性能也相较Python2有一定的提升;

  

  回答思路2:

  时间线:

  截止2014年,哈佛、麻省理工、伯克利、卡内基等美国顶尖高校将Python作为教学语言;

  2018年开始,Python雄踞各大年度最佳编程语言排行榜榜首(IEEE, TIOBE)

  空间线:

  Python特性:动态、解释、脚本、跨平台...

  解释器:cpython,jpython,ipython,jit

  Python2,3特性

 

  思路串联:Python特性(解释、动态、脚本)-> 当前发展 -> 解释器及性能优化 -> 埋下一个问题引子

 

  示例答案2:Python语言和C++, Java等其他编译型语言不一样,它是一种动态解释型脚本语言,代码在执行时会一行一行的解释成CPU能理解的机器码。同时它又是跨平台的,可以允许在windows,linux,mac等系统上,同样的程序逻辑,可能C语言需要1000行代码,java有100行,而Python实现可能只需要20行,这极大程度上提升了企业的项目开发效率。

  记得之前看到一篇报道说,到2014年为止,哈佛、麻省理工、伯克利等顶尖高校都已经使用Python作为教学语言,而最近这一两年来Python也多次被各大机构评为年度最佳编程语言。对于企业项目后台开发而言,不是说一定需要使用Python开发,但至少应该是一个首选考虑项,当然Python本身从根本上来说性能是比不上C/C++这些编译型语言,但现在语言本身的性能差距在实际开发的过程中,相对业务功能合理性设计、代码编写架构质量等等,语言底层本身造成的性能损失越来越可以忽略不计;针对于一些特定的功能模块,Python当前也出现了pypy,JIT等大幅提高Python程序运行效率的相关技术,能够满足大多数功能需求业务场景。

  具体选用Python后,新项目推荐使用python3,2008年Python3发布后,十几年来Python3生态圈三方库已经非常完备和齐全,而官方已宣布Python2在2020年将不再维护,另外Python3本身性能也相较Python2有一定的提升;

 

  回答思路3:

  时间线:

  20世纪60年代,UNIX诞生,贝尔实验室发明B语言(过于简单,数据无类型)

  1972年,C语言诞生(面向过程),重写UNIX;

  1995年,Java出现;(面向对象)

  2000年,第一个稳定的Python2版本发布;

 

  空间线:

  语言的本质

  Python行业发展(人工智能、云计算、大数据...)

  Python开源生态圈

  Python2,3特性

 

  思路串联:语言进化 -> 语言本质 -> Python当前发展(应用产业及开源生态圈)-> 留下一个问题引子(此思路不说Python缺陷,留下两个下一问题引子)

 

  示例答案3:恩...这个问题我是这么看的,上世纪60年Unix诞生时,贝尔实验室是使用的B语言,解决了面向机器的汇编语言极其复杂问题,然后到72年,面向过程的C语言出现,再到95年Java诞生,面向对象的思想极大的提升了程序猿的开发效率。2000年第一个稳定的Python2版本,20年来其简单高效的特质大大降低了研发人员的学习和开发成本;

  编程语言的本质是人与机器沟通的工具,将人类希望机器做的事翻译成机器本身能够理解的指令;语言发展进化的历史也已经表明,越符合人类自身思维逻辑及习惯的编程语言将越受到大众欢迎。目前从云端、客户端,到物联网终端,python应用无处不在,同时也是人工智能首先的编程语言(Python在在人工智能上的优势至今无人能够撼动)。Python当前也已经具备了非常完备丰富的开源三方生态圈(比如web框架tornado,sanic, 运维监控zabbix,游戏引擎firefly等等不胜枚举)。对于大多数企业新后台项目开发,个人倾向于推荐Python作为首选语言。

  具体选用Python后,新项目推荐使用python3,2008年Python3发布后,十几年来Python3生态圈三方库已经非常完备和齐全,而官方已宣布Python2在2020年将不再维护,另外Python3本身性能也相较Python2有一定的提升;

 

2. Python是否存在内存泄露

思路:

空间线:

  内存管理的方式

  波音737事件

  引用计数

  循环引用

思路串联:

简述内存管理的方式->自动管理分配的弊端(举例波音)-> 循环引用 -> 引用计数 -> 留下一个问题引子

示例答案:

  编程语言中内存的管理和分配一般有两种方式,程序手动回收或者系统自动回收。前者的代表性语言如C++, 而Python使用的是系统自动回收的机制。自动化管理的方式大大提供程序猿开发效率的同时,但在一些特殊的场景下也可能出现错误处理的情况,就像前段时间的美国波音737事件,传感器错误数据引发飞机自动化系统操作强制下降,最终酿成事故。

  在Python中是可能出现内存泄露的,比如当对象A中引用了对象B,同时对象B中又引用了对象A,即出现了循环引用。Python中使用的引用计数的内存管理方式,此时A和B的引用计数将永远大于等于1,也就是说解释器将无法自动回收对象A和B的内存空间,也即产生了内存泄露。随着该模块对象创建次数的逐渐增加,在操作系统负载上可以看到该Python程序内存持续上升,直到系统资源不够进程被强制中止。

 

3. 过往的项目中有没有出现过性能问题?

思路:

空间线:

  内存管理的方式

  波音737事件

  引用计数

  循环引用

 思路串联:直面回答有(内存泄露问题)-> 回归到Python内存泄露示例上

示例答案:

  有,有出现过性能问题。之前我参与的一个项目中有出现过内存泄露的情况。

      当时经过跟踪后发现有一个项目代码过程中有一个对象A对象B,同时对象B中又引用了对象A,即出现了循环引用。编程语言中内存的管理和分配一般有两种方式,程序手动回收或者系统自动回收。前者的代表性语言如C++, 而Python使用的是系统自动回收的机制。自动化管理的方式大大提供程序猿开发效率的同时,但在一些特殊的场景下也可能出现错误处理的情况,就像前段时间的美国波音737事件,传感器错误数据引发飞机自动化系统操作强制下降,最终酿成事故。

  Python中使用的引用计数的内存管理方式,循环引用出现时对象的引用计数将永远大于等于1,也就是说解释器将无法自动回收对象A和B的内存空间,也即产生了内存泄露。

 

4. 什么是协程

思路:

时间线:

20世纪60年代,进程的概念随着多道操作系统诞生而引入;

80年代,出现了能独立运行的基本单位--线程;

协程最早产生于1963年;

 

空间线:

进程的特性及多进程应用场景

线程的特性及多线程应用场景

协程的特性及应用场景

GIL

 

思路串联:

协程历史->进程特性、多进程-->线程特性、多线程-->协程特性及使用-->GIL引子

 

示例答案:

  协程的概念最早提出于1963年,但由于其并不符合当时崇尚的的“自顶向下”的程序设计思想,未能成为当时主流编程语言的一部分;

      20世纪60年代,进程的概念被引入,进程作为操作系统资源分配和调度的基本单位,多进程的方式在很长时间内大大提高了系统运行的效率,虽然中间产生了Copy-On-Write等技术的出现,但进程的频繁创建和销毁代价较大、资源的大量复制和分配耗时仍然较高,于是80年代出现了能够独立运行的单位--线程。多线程之间可以直接共享资源,同时线程之间的通信效率又远高于进程间,将任务并发的性能再次向前推进了一大步。不过多线程也有其不足的地方,虽然线程之间切换代价相较多进程小了很多,但一些场景下线程CPU时间片的大量切换其实是做了很多不必要的无用功,特别是Python中因为GIL锁的存在,其多线程很多时候并不能提供程序运行效率,于是协程的概念又开始发挥了作用,是一个线程在执行,只有当该子程序内部发生中断或阻塞时,才会交出线程的执行权交给其他子程序,在适当的时候再返回来接着执行。这省去了线程间频繁切换的时间开销同时也解决了多线程加锁造成的相关问题;

      具体的生产环境中,Python项目经常会使用多进程+协程的方式,规避GIL锁的问题,充分利用多核的同时又充分发挥协程高效的特性。

 

5. 知道mysql的事务隔离吗?/事务隔离分哪几个级别?/事务隔离性怎么保证/...

   回答思路:

   空间线:

   事务ACID概念

   事务隔离四个级别(概念及优缺点)

   MySQL事务隔离性和其他DB区别

   

   思路串联:事务ACID-> 事务隔离四个级别 ->留MVCC/GAP问题引子

 

   示例答案:

    数据库支持事务本身需要有具备四个特性:原子性、一致性、隔离性和持久性,也即ACID。其中事务的隔离性简单来说就是并发执行的多个事务之间互不干扰。

    事务隔离总体分为四个级别:第一个是RU(未提交读),该级别事务内容易出现脏读的情况,即事务A读到了事务B没有提交的数据;为了解决脏读问题,可以提高事务隔离级别到RC(提交读),此时事务A不会读到其他事务未提交的数据,但又产生了一个新的现象:事务A执行的过程中,有可能另外一个事务B提交了数据,此时事务读取的数据和之前不一致,即出现了不可重复读的问题;所以mysql的InnoDB本身默认采用了第三个事务隔离级别RR(可重复读),该级别使用MVCC(多版本并发控制)解决重复读的问题,一般的RR级别会出现幻读的问题,及同一个事务多次执行同一个select,读取到的数据行发生了改变,这是因为数据行发生了行数减少或者新增;而最高的事务隔离级别是SE(可序列化),该方式下事务相当于串行执行,解决了脏读、不可重复读、幻读等问题,但对性能和效率的影响很大,生产环境中很少会使用该隔离级别;

    具体到mysql中,mysql默认的RR级别有一些特别,因为其引入了GAP LOCK(间隙锁)的概念,可在RR级别即可解决幻读的问题;另外一个特性是mysql里的MVCC只解决读-写的阻塞问题,写-写依然还是阻塞的。

 

6. MySQL和MongoDB区别?

思路:

时间线:

2015年,MySQL5.7发布,开始支持json;

2018年,MySQL8.0版本,支持文档存储;

2018年,MongoDB4.0发布,支持多文档事务;

空间线:

MySQL存储引擎及底层存储B+树

Mongodb存储引擎及底层存储B树

DB选型考虑因素

思路串联:

MySQL存储引擎及结构介绍--MongoDB存储引擎及结构介绍-->MySQL和MongoDB区别(夹杂时间线)--> DB选型因素--> 埋下一个问题引子(事务相关)

 

示例答案:

     MySQL是关系型数据库的一种,其存储引擎有MyISam, InnoDB,Merge等,目前在业界中大多使用的支持事务InnoDB存储引擎,从15年MySQL5.7开始,MySQL开始支持json格式(开始向nosql数据库靠近);而MongoDB去年8月份发布的最新版本4.0开始支持多文档事务,当前其默认的存储引擎wiredtiger性能非常卓越;

     mysql和MongoDB数据库发展越来越类似,都在取其精华,在具体的数据库选型时,两种DB底层的实现机制可能是一大考虑因素。mysql索引底层是用B+树实现的,而MongoDB则是采取的B树,B树的结构也就决定了MongoDB在海量读写的情况下性能比mysql卓越(时间复杂度是O(1)-O(logN)), 而MySQL B+树的特性也决定了MySQL更适合多区间范围查询的业务需求。 当然,在具体的项目DB选择过程中,我们还需要考虑到成本、团队成员的意愿、技术栈等情况。

     总的来说,在当前的情况下,如果是海量数据高并发读写,从技术的角度推荐使用MongoDB,如果数据结构相对统一,同时对于事务有较高要求,个人倾向于MySQL。

 

7. 什么是IO多路复用?/epoll和select,poll有什么区别?

回答思路:

时间线:

1983年,select出现

1997年,poll出现

2002年,epoll出现

空间线:

多路复用概念

select、poll、epoll区别

select、poll、epoll适用场景

epoll和协程

思路串联:

多路复用概念--> 多用复用发展历史及使用场景(select->poll->epoll)--> 留下一个问题引子(协程)

示例答案:

  I/O多路复用,I/O就是指的我们网络I/O,多路指多个TCP连接(或多个Channel),复用指复用一个或少量线程。

  第一次实现IO多路复用的概念是在1983年select机制的出现,在很长的时间内select都满足多路复用的各类需求,但随着技术和社会的发展,select本身1024个连接上限逐渐开始不够用了,于是在1997年poll机制应运而生,poll机制去掉了select的很多问题,比如1024链接数限制,但同时本身也存在着select一样的非线程安全缺陷,同时轮询的方式在很多场景下会造成性能和资源的浪费。2002年时,一种新的多用复用机制epoll随之产生,epoll采用的是事件触发的机制,放弃了select和poll轮询的实现方式,同时又是线程安全的,大大提高了实际场景中的并发处理能力;但epoll目前也存在一些不足的地方,比如只有Linux系统才支持,同时在一些特定的场景下,比如绝大部分TCP链接都处于就绪的状态,此时比较适合轮询的方式。

  总体而言,目前多路复用技术中epoll相对使用的较为广泛,比如在Python中tornado的协程很多时候就是通过epoll机制进行切换调度的。

 

8. 了解过tornado或sanic吗?/有木有接触过其他web框架

思路:

空间线:

django设计哲学

flask、tornado、sanic特性

同步和异步

阻塞和非阻塞

项目框架选型

  

思路串联:

各框架特性--同步异步、框架选型--> 埋下一个问题引子(协程)

 

示例答案:

  有了解过tornado和sanic框架,不过之前公司的项目中大多框架选用的是django,少部分项目使用的flask。其中django设计哲学是简便、快速,强调代码复用,大而全是代表特性,而flask相对而言小而精一点。tornado和sanic是异步框架,性能都非常卓越,tornado是Facebook开源的一个项目,目前应用亦颇为广泛;sanic是基于Python3.5的近些年兴起的框架,用到了很多Python3的新特性。

  一般在框架选型过程中,如果希望开发过程中框架有丰富的三方插件,推荐使用django和flask,然后部署时使用NGINX+uwsgi提高并发;如果纯粹的后端项目,更加追求性能,可以考虑使用tornado或者sanic等异步框架,像tornado、sanic这些支持协程的框架确实比较适合大多数的高并发网络IO处理。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!