作者:胡阳
古木阴中系短篷, 杖藜扶我过桥东。 沾衣欲湿杏花雨, 吹面不寒杨柳风。

哈罗大家好, 我是Python的新员工干货狗。 没错! 就是狂拽帅气吊炸天、 人见人爱、花见花开、 专门推荐各种技术干货的那种。 大家可以叫我狗哥!
据说看完我推荐的东西,技术能力都会增长好几倍。 什么?你说我吹牛? 这年头,给自己加点戏怎么了? 啊?你们不喜欢吹牛B风格啊? 那好,我低调点。

初到此地,小弟还在熟悉环境, 还请各位大佬们见谅。 小长假刚结束, 人事就通知我赶紧来入职, 说有个紧急任务要给我。 于是我就带着满腔热血来了。

原来有读者连续轰炸我们的微信后台。 目测是一篇八百字小作文, 控诉自己面试被刷经历。 讲到激动时刻还出现了刺眼的文词, 有种随时扛锹挖面试官祖坟的架势。
我们想告诉这位小兄弟,年轻人火气别那么大, 虚心请教才能成大事嘛。 让狗哥来帮帮你。

为了让这个你们顺利通过面试, 这周我出卖帅相, 邀请了一位专家来给我们指点下。 忘了说, 这位同学是 Java 转行 Python Web,
于是,公司的人给狗哥安利了胡阳(the5fire)老师。 说他也有过相同的转行经历, 而且现在已经成长为一位大神。 我一看,这个行啊!
狗哥正想给转(行)和不转(行)、跳和不跳之间犹豫的小可爱们, 来一支这样的定海神针呢。 也愿大家面试顺利, “吹面”不寒杨柳风。

哎呀!不多说了! 胡阳老师就要来了, 赶紧先看看这 10 道面试题。
1、PEP 8 是什么?Python 之禅(import this)是什么?

2、Python 常用的容器类型有哪些以及它们之间的差别?

3、解释下闭包是什么,以及日常中什么场景会用到?

4、GIL 是什么?它的影响和具体原理是什么?

5、进程、协程、线程分别是什么,以及区别是什么?

6、如何理解 Django 被称为 MTV 模式?

7、解释下什么是 ORM 以及它的优缺点是什么?

8、如何排查 Django 系统中的性能问题?

9、Django 系统中如何配置数据库的长连接?

10、如何部署并监控 Django 系统?

咳咳!别说,有几个问题也把狗哥难住了。是时候请出胡阳老师了!掌声响起来~

Hi,我是胡阳,网名 the5fire,前搜狐资深开发工程师,现任知乎资深开发工程师,负责部分业务的后端开发和团队管理。同时也是腾讯云最具价值专家(TVP)。

我平时喜欢通过代码来构建一些有价值的东西,有着近 10 年编程经验和写博客经验,爱好记录和分享自己的经验。

2011 年Java转到Python后,主要熟悉 Web 框架 Django 和 Tornado。赞叹于Python 的开发效率,欣赏 Django
完备的功能点对实际项目开发中程序员生产力的提升。

今天狗哥请我来帮一位读者解决面试的问题,其实我们都是从这个阶段过来的。所以能帮上大家也是比较开心的。那今天我从面试的角度给大家归纳下 Django
工程师面试时面试官都会问些啥。


其实解析这些问题之前,大家要明白一个基本原则:面试的目的是找到合适的候选人,提问的目的是为了考察当前候选人对当前岗位的匹配度。所以,所有的问题基本上都会围绕着工作内容来展开,但最终还是会落到具体的技术点上。


不知道你有没有自己思考下对应问题的答案。这十个问题可能只是面试的开始,要知道技术类的面试要是聊的嗨了,聊一两个小时是常事儿。所以,如果你在面试,这十个问题你要怎么来答呢?

<>Q1:PEP8是什么?Python之禅(import this)是什么?

这题是考察你对编码规范的认识,无论是自己写代码还是在团队中写代码,了解并遵循代码规范是很基础的要求。企业中在提交代码后都会有对应的工具来对代码进行检查,比如
pep8、flake8、pylint 等,但是 PEP 8 是什么一定要了解。

即 Style Guide for Python Code(Python编码风格指南)。如果面试时不知道什么是 PEP 8
,那聊起来想必不会很愉快。速战速决的面试,如果不是你把面试官“秒杀”了,那就是面试官把你“秒杀”了,大部分是后者。Python 之禅,也就是 import
this。这属于对 Python 文化的了解了。什么意思?你去 Python shell 里执行一下:import this,然后搜索下答案自然就出来了。

<>Q2:Python常用的容器类型有哪些以及它们之间的差别?

这是一道基础题。如果被问到了这个问题,说明面试官在探测你对 Python 基础的掌握。如果不知道,那就会被“秒杀”。当然聊得好了,也可以聊到实现原理层面。

在 Python 中常用的数据类型,有一些是基础数据类型,比如 int、bool、string,还有容器类型,比如 list、set、dict
等。所有的类型又可以氛分为:可变类型和不可变类型(不知道是什么的可以动手搜索一下)。单说容器类型,每种容器类型都有使用的场景,比如 list
可以存放不同类型的元素,特点是支持索引和切片操作,支持 insert 和 pop 操作,属于可变类型。由此也可以展开很多面试题中遇到的坑,比如说这个代码:

然后再来说到 tuple,也可以当做列表,支持迭代、索引、切片等操作,但因为它是不可变类型,所以不支持 append、insert
等操作,为什么不支持呢?在从应用上来说,在实际编程中经常会用到它,比如:参数传递,解包。这一部分可以继续聊下去的就是namedtuple。再然后就是 set
和 dict,它们跟 list 和 tuple有这么几个差别:1. 存放的值不是顺序的;2. 无法通过索引获取到数据;3. 存放的元素不可重复,并且必须是
hashable(可哈希的),针对 key 来说;4. 更快的查找速度,因为是通过哈希表来存储的。当然还可以继续深入 set 和 dict
的原理,如何解决哈希碰撞。

<>Q3:解释下闭包是什么,以及日常中什么场景会用到?

闭包是指持有了自由变量的函数,那怎么理解呢,用代码来看一下:

这就是个典型的场景。

<>Q4:GIL 是什么?它的影响和具体原理是什么?

GIL:Global Interpreter
Lock(全局解释器锁)。具体表现就是:在一个进程中,同一时刻只能有一个线程能到解释器,为什么只能有一个线程拿到解释器呢?因为在 CPython
中,内存管理不是线性安全的,所以,为了避免多个线程同时访问到一个对象,就有了这么一个锁。顺带着也提到了线程安全的概念,有了 GIL 了,那么 Python
中有哪些类型是线程安全的呢?哪些不是呢?又是一个新的问题。那么 GIL 的影响是什么呢?就是同一时刻只有一个线程在真实执行,对于 CPU
密集型的应用影响比较大,对于 IO 密集型的应用影响没那么大。当然还可以具体展开来说。

<>Q5:进程、协程、线程分别是什么,以及区别是什么?

从操作系统角度来讲,进程是资源分配单元,线程是执行单元,多个线程可以共享所在进程的资源。而协程是从程序运行角度来叫,是由用户(程序)控制和调度的一个过程,在
Python 中,协程是一个包含了 yield 的函数,比如下图:

在Python 3里面你可以用 asyncio.iscoroutine(coro) 来判断是否为协程。需要了解的是在协程执行时,是通过 event
loop 来调度的。如果聊到这,可能会接着聊下 Tornado 的 IOLoop
的事。总体来说,协程可以理解为更轻量级的线程,能够在单线程中运行多个协程。需要注意的是,在 Python
中协程执行是串行的,这个是由于它的调度机制决定的,这点不同于 Golang。

<>Q6:如何理解 Django 被称为 MTV 模式?

如果是我来问这个问题,这个题就是面向对象设计和设计模式的开始。简单来说大家耳熟能详的模式叫: MVC。说是 Model View Controller,而在
Django 中因为 Template 来处理视图展现,所以称为:
MTV。接下里会问到的就是分层的概念,有句话叫:“没有什么问题是不能通过增加一层解决的,如果有,那就再加一层。”当然还会有设计模式的一些原则等着你,比如开-闭原则、单一职责原则等。

<>Q7:解释下什么是 ORM 以及它的优缺点是什么?

ORM:Object Relational Mapping(对象关系映射),它做的事就是帮我们封装一下对数据库的操作,避免我们来写不太好维护的 SQL
代码。优点就是让我们写的代码更容易维护,因为里面不用夹杂着各种 SQL 代码。缺点是失去了 SQL 的灵活,并且越是通用的 ORM 框架,性能损耗会越大。

说到性能损耗,可以接着聊的是 Django 中的 raw sql,也就是说 Model.objects.raw
这个方法的使用,它的作用、原理、性能提升等。还可以继续聊另外一个老生常谈的问题:N+1 的问题。

<>Q8:如何排查 Django 系统中的性能问题?

对于 Django 这样一个非常成熟的框架来说,丰富的周边能够让我们快速的找到别人开源出来的优秀插件,比如说
Django-debug-toolbar,或者是 Django-silk 。但是一个基础问题是:在 Django 的 settings 中,设置DEBUG =
True 和 DEBUG = False 的差别是什么?还可以聊的是对于 Django
处理请求到返回响应的具体流程。因为只有熟悉了整体流程,才能在合理的位置进行排查。比方说,当我们判断可能是数据库的问题时,那可能需要在 Model
层的某个方法上加上执行时间监测的逻辑。如果是 View 层的其他逻辑导致的,可能会在 Middleware 上增加执行时间监测的逻辑。

<>Q9:Django 系统中如何配置数据库的长连接?

这涉及到 Django 如何处理数据库连接细节的问题。默认情况下对于每一个请求 Django
都会建立一个新的数据库连接。这意味着当请求量过大时就会出现数据库(MySQL)的 Too many connection
的问题,对于这个问题,在其他的语言框架中有连接池这样的东西来减少数据库的连接数,来提升连接的使用效率。而在 Django
中,为了处理这一问题,增加了一个配置: CONN_MAX_AGE,在 settings 的 DATABASES 配置中。配置了该选项后,Django
会跟数据库保持链接(时长取决于 CONN_MAX_AGE 设定的值 ),不再会针对每个请求都创建新的连接了。但是需要注意的是,这跟数据库连接池的概念还不太一样。

<>Q10:如何部署并监控 Django 系统?


这个就是考察候选人对于真实项目的部署和线上问题排查的了解了。如果没有真实工作过,可能不太有概念。首先需要理解的是开发的流程,代码在程序员的电脑(开发机)上开发完成,然后部署到测试环境进行测试,这个过程可能是自动的(由
GitLab CI 触发或者其他类似逻辑),也可能是需要人工操作的(比如使用 Fabric 或者
ansible)手动执行部署操作。然后测试同学进行测试,没问题之后,代码合并到主分支(涉及Git相关的使用流程),再部署上线。


这时系统就可以对外提供服务了,那么问题来了,用户的访问是如何到你部署的系统中来的?再来说监控。监控的目的是为了保证程序的正常运行,如果出现问题我们可以及时发现并修复。所以,简单来说有两个确定的指标可以观察,第一个是状态码,对于
HTTP 服务来说,监控非 200 的状态码的数量是很有必要的;第二个就是应用内的异常监控,这个就是 Sentry
之类的系统来做了,通过它可以收集到具体的异常详情,完成的 Traceback,可以帮助我们快速地定位问题所在。


虽然说只有十个问题,但是在正式聊的时候,每个问题都是可以层层追问的,其实面试有个原则,就是:要追问到候选人答不出来,或者面试官不知道该问什么为止,因为需要确定候选人的技术掌握的边界(深度)。

怎么样?看过这十题,是不是觉得茅塞顿开。我们也要感谢胡阳老师的分享。最后,狗哥还想推荐正在修炼 Django 的你来翻翻这本。



好啦!今天狗哥的分享就到这里了。没看够的就等下次吧!我昨天刚来这里,还不太了解你们的喜好。所以,别跟我女朋友似的,没事总让我猜猜猜。咱好哥们,你想看啥直接告诉我就成。不行了,我得开溜了,我女朋友在呼唤我,哎呀呀,记得买书哦。
购书链接:https://h5.youzan.com/v2/goods/1yf7gljw34ti7
<https://h5.youzan.com/v2/goods/1yf7gljw34ti7>
扫码下方二维码也可以哦

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信