来源:图灵教育
作者:胡阳
哈罗大家好,
我是人邮的新员工干货狗。
没错!
就是狂拽帅气吊炸天、
人见人爱、花见花开、
专门推荐各种技术干货的那种。
大家可以叫我狗哥!
据说看完我推荐的东西,
技术能力都会增长好几倍。
什么?你说我吹牛?
这年头,给自己加点戏怎么了?
那好,我低调点。
初到此地,小弟还在熟悉环境,
还请各位大佬们见谅。
昨天领导说有个紧急任务要给我。
原来有读者连续轰炸我们的后台。
目测是一篇八百字小作文,
控诉自己面试被刷经历。
讲到激动时刻还出现了刺眼的文词,
有种随时扛锹挖面试官祖坟的架势。
我们想告诉这位小兄弟,
年轻人火气别那么大,
虚心请教才能成大事嘛。
让狗哥来帮帮你。
为了让这个读者顺利通过面试,
这周我出卖帅相,
邀请了一位专家来给我们指点下。
忘了说,
这位同学是Java转行PythonWeb,
于是,公司的人给狗哥安利了
胡阳(the5fire)老师。
说他也有过相同的转行经历,
而且现在已经成长为一位大神。
我一看,这个行啊!
狗哥正想给转(行)和不转(行)、
跳和不跳之间犹豫的小可爱们,
来一支这样的定海神针呢。
也愿大家面试顺利,
“吹面”不寒杨柳风。
哎呀!不多说了!
胡阳老师就要来了,
赶紧先看看这10道面试题。
PEP8是什么?Python之禅(importthis)是什么?Python常用的容器类型有哪些以及它们之间的差别?解释下闭包是什么,以及日常中什么场景会用到?GIL是什么?它的影响和具体原理是什么?进程、协程、线程分别是什么,以及区别是什么?如何理解Django被称为MTV模式?解释下什么是ORM以及它的优缺点是什么?如何排查Django系统中的性能问题?Django系统中如何配置数据库的长连接?如何部署并监控Django系统?
咳咳!别说,有几个问题也把狗哥难住了。是时候请出胡阳老师了!掌声响起来~
Hi,我是胡阳,网名the5fire,前搜狐资深开发工程师,现任知乎资深开发工程师,负责部分业务的后端开发和团队管理。同时也是腾讯云最具价值专家(TVP)。
我平时喜欢通过代码来构建一些有价值的东西,有着近10年编程经验和写博客经验,爱好记录和分享自己的经验。
年Java转到Python后,主要熟悉Web框架Django和Tornado。赞叹于Python的开发效率,欣赏Django完备的功能点对实际项目开发中程序员生产力的提升。
今天狗哥请我来帮一位读者解决面试的问题,其实我们都是从这个阶段过来的。所以能帮上大家也是比较开心的。那今天我从面试的角度给大家归纳下Django工程师面试时面试官都会问些啥。
其实解析这些问题之前,大家要明白一个基本原则:面试的目的是找到合适的候选人,提问的目的是为了考察当前候选人对当前岗位的匹配度。所以,所有的问题基本上都会围绕着工作内容来展开,但最终还是会落到具体的技术点上。
不知道你有没有自己思考下对应问题的答案。这十个问题可能只是面试的开始,要知道技术类的面试要是聊的嗨了,聊一两个小时是常事儿。所以,如果你在面试,这十个问题你要怎么来答呢?
Q1:PEP8是什么?Python之禅(importthis)是什么?
这题是考察你对编码规范的认识,无论是自己写代码还是在团队中写代码,了解并遵循代码规范是很基础的要求。企业中在提交代码后都会有对应的工具来对代码进行检查,比如pep8、flake8、pylint等,但是PEP8是什么一定要了解。
即StyleGuideforPythonCode(Python编码风格指南)。如果面试时不知道什么是PEP8,那聊起来想必不会很愉快。速战速决的面试,如果不是你把面试官“秒杀”了,那就是面试官把你“秒杀”了,大部分是后者。Python之禅,也就是importthis。这属于对Python文化的了解了。什么意思?你去Pythonshell里执行一下:importthis,然后搜索下答案自然就出来了。
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:解释下闭包是什么,以及日常中什么场景会用到?
闭包是指持有了自由变量的函数,那怎么理解呢,用代码来看一下:
日常使用场景是什么呢?最常用会用到的地方就是装饰器,上面的示例代码也能看出来,比如我曾写过Cache的演进部分,部分代码如下:
这就是个典型的场景。
Q4:GIL是什么?它的影响和具体原理是什么?
GIL:GlobalInterpreterLock(全局解释器锁)。具体表现就是:在一个进程中,同一时刻只能有一个线程能到解释器,为什么只能有一个线程拿到解释器呢?因为在CPython中,内存管理不是线性安全的,所以,为了避免多个线程同时访问到一个对象,就有了这么一个锁。顺带着也提到了线程安全的概念,有了GIL了,那么Python中有哪些类型是线程安全的呢?哪些不是呢?又是一个新的问题。那么GIL的影响是什么呢?就是同一时刻只有一个线程在真实执行,对于CPU密集型的应用影响比较大,对于IO密集型的应用影响没那么大。当然还可以具体展开来说。
Q5:进程、协程、线程分别是什么,以及区别是什么?
从操作系统角度来讲,进程是资源分配单元,线程是执行单元,多个线程可以共享所在进程的资源。而协程是从程序运行角度来叫,是由用户(程序)控制和调度的一个过程,在Python中,协程是一个包含了yield的函数,比如下图:
在Python3里面你可以用asyncio.iscoroutine(coro)来判断是否为协程。需要了解的是在协程执行时,是通过eventloop来调度的。如果聊到这,可能会接着聊下Tornado的IOLoop的事。总体来说,协程可以理解为更轻量级的线程,能够在单线程中运行多个协程。需要注意的是,在Python中协程执行是串行的,这个是由于它的调度机制决定的,这点不同于Golang。
Q6:如何理解Django被称为MTV模式?
如果是我来问这个问题,这个题就是面向对象设计和设计模式的开始。简单来说大家耳熟能详的模式叫:MVC。说是ModelViewController,而在Django中因为Template来处理视图展现,所以称为:MTV。接下里会问到的就是分层的概念,有句话叫:“没有什么问题是不能通过增加一层解决的,如果有,那就再加一层。”当然还会有设计模式的一些原则等着你,比如开-闭原则、单一职责原则等。
Q7:解释下什么是ORM以及它的优缺点是什么?
ORM:ObjectRelationalMapping(对象关系映射),它做的事就是帮我们封装一下对数据库的操作,避免我们来写不太好维护的SQL代码。优点就是让我们写的代码更容易维护,因为里面不用夹杂着各种SQL代码。缺点是失去了SQL的灵活,并且越是通用的ORM框架,性能损耗会越大。
说到性能损耗,可以接着聊的是Django中的rawsql,也就是说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)的Toomanyconnection的问题,对于这个问题,在其他的语言框架中有连接池这样的东西来减少数据库的连接数,来提升连接的使用效率。而在Django中,为了处理这一问题,增加了一个配置:CONN_MAX_AGE,在settings的DATABASES配置中。配置了该选项后,Django会跟数据库保持链接(时长取决于CONN_MAX_AGE设定的值),不再会针对每个请求都创建新的连接了。但是需要注意的是,这跟数据库连接池的概念还不太一样。
Q10:如何部署并监控Django系统?
这个就是考察候选人对于真实项目的部署和线上问题排查的了解了。如果没有真实工作过,可能不太有概念。首先需要理解的是开发的流程,代码在程序员的电脑(开发机)上开发完成,然后部署到测试环境进行测试,这个过程可能是自动的(由GitLabCI触发或者其他类似逻辑),也可能是需要人工操作的(比如使用Fabric或者ansible)手动执行部署操作。然后测试同学进行测试,没问题之后,代码合并到主分支(涉及Git相关的使用流程),再部署上线。
这时系统就可以对外提供服务了,那么问题来了,用户的访问是如何到你部署的系统中来的?再来说监控。监控的目的是为了保证程序的正常运行,如果出现问题我们可以及时发现并修复。所以,简单来说有两个确定的指标可以观察,第一个是状态码,对于HTTP服务来说,监控非的状态码的数量是很有必要的;第二个就是应用内的异常监控,这个就是Sentry之类的系统来做了,通过它可以收集到具体的异常详情,完成的Traceback,可以帮助我们快速地定位问题所在。
虽然说只有十个问题,但是在正式聊的时候,每个问题都是可以层层追问的,其实面试有个原则,就是:要追问到候选人答不出来,或者面试官不知道该问什么为止,因为需要确定候选人的技术掌握的边界(深度)。
怎么样?看过这十题,是不是觉得茅塞顿开。我们也要感谢胡阳老师的分享。最后,狗哥还想推荐正在修炼Django的你来翻翻这本。
快速上手Django,
资深开发工程师the5fire十多年开发经验总结
作者:胡阳
作者通过开发一个常见的系统,把自己生产环境中的经验融合进去,通过项目不断帮助读者构建关于Django的知识体系,最终达到让读者能够通过Django开发线上Web系统。书中内容涉及需求分析、技术选型、开发、Djangoadmin、版本管理与协作、面向用户的页面开发、引入前端样式框架、优化与调试、上线前的准备等。
好啦!今天狗哥的分享就到这里了。没看够的就等下次吧!我昨天刚来图灵,还不太了解你们的喜好。所以,别跟我女朋友似的,没事总让我猜猜猜。咱好哥们,你想看啥直接告诉我就成。
文末畅聊
快来跟狗哥说说,你在面试中遇到过哪些印象深刻的人和事,可能是面试你的人,也可能是你面试过的人。如何在面试中“秒杀”面试官,相信你自己也有着独到的见解。快来交流一下吧!