汇集天下武学——Python面试宝典

导语:本人最近刚离职,抱着一腔热情踏上了漫漫求职路,现将本人面试时遇到的问题汇总一下,供大家交流学习,望不吝惜,最后打一波广告,学习Python可进群647094497,我会分享一点资料给大家,金麟岂是池中物,一入风云便化龙

 

流量+      python爬虫工程师

一、FastDFS的工作原理和配置

       1.什么是FastDFS

          FastDFS 是用 c 语言编写的一款开源的分布式文件系统。

          使用 FastDFS 很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

          FastDFS 架构包括Tracker server和Storage server。

          Tracker server 作用是负载均衡和调度,通过 Tracker server在文件上传时可以根据一些策略找到 

          Storage server提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。

          Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上, 

          可以将 storage 称为存储服务器。

 

二、Numpy和Pandas的区别

       Numpy是以矩阵为基础的数学计算模块,纯数学。Numpy只能处理数值计算

       Pandas提供了一套名为DataFrame的数据结构,比较契合统计分析中的表结构,

       并且提供了计算接口,可用Numpy或其它方式进行计算。

       Pandas不但可以处理数值计算(基于Numpy)还可以处理其他类型的数据

 

三、scrapy框架中如何配置代理IP

       1.需要在middlewares.py中自定义一个中间件来配置代理IP:

        

       

        2.然后在settings.py中配置中间件:

        

 

四、使用request模块实现爬虫的全过程

        1.发送网络请求,返回响应数据:

            response = requests.get(url,headers=headers)

        2.对响应数据进行解析:

            response.content.deocde()

 

五、如何实现url地址去重

       可以使用基于布隆过滤器(Bloom Filter)的存储。

       布隆过滤器的基本算法思想主要是利用一个长度为M的位数组,且初始化为零,

       一个元素通过K(K<

       当再有数据字符串进来要存储的时候,比对该位置是否为1,如果是1就舍弃,

       如果是0则继续存储。以此来达到去重的效果。

 

 

华为外包     python开发工程师

一、简述多线程、多进程、协程

       1.多线程(threading):

                在⼀个进程内的所有线程共享全局变量,方便在多个线程间共享数据            

                缺点就是,如果多个线程同时对同⼀个全局变量操作,

                会出现资源竞争问题,从而数据结果会不正确,解决方法是使用互斥锁

       2.多进程(multiprocessing):

                进程不共享全局变量,相互独立,安全性较高

                缺点是会加大系统消耗

       3.协程(Coroutines):

                协程是一种比线程更加轻量级的存在,一个线程也可以拥有多个协程

                协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。

                协程调度切换时,将寄存器上下文和栈保存到其他地方,

                在切回来的时候,恢复先前保存的寄存器上下文和栈,

                直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,

                所以上下文的切换非常快

 

二、异步编程

       Python通过协程(coroutine)来实现异步编程

 

三、redis的内存淘汰机制

       1.过期键删除策略:

                定时删除:在设置键的过期时间的同时,创建一个定时器(timer ),

                当过期时间到了后立即执行对键的删除操作。

 

                惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,

                                 如果过期的话,就删除该键;如果没有过期,就返回该键。

 

                定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。

                                 至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。

 

       2.内存淘汰机制:

                当目前使用的内存超过了设置的最大内存,就要进行内存释放了, 

                当需要进行内存释放的时候,需要用某种策略对保存的的对象进行删除。

                Redis有六种策略(默认的策略是volatile-lru):

                        volatile-lru:使用LRU算法进行数据淘汰(淘汰上次使用时间最早的,且使用次数最少的key),

                                             只淘汰设定了有效期的key ;

                        allkeys-lru:使用LRU算法进行数据淘汰,所有的key都可以被淘汰;

                        volatile-random:随机淘汰数据,只淘汰设定了有效期的key;

                        allkeys-random:随机淘汰数据,所有的key都可以被淘汰;

                        volatile-ttl:淘汰剩余有效期最短的key;

                        no-enviction:不删除任意数据(但redis还会根据引用计数器进行释放),

                                                这时如果内存不够时,会直接返回错误 。

 

 

四、数据库事务的ACID特性:

       ACID是Atomic(原子性)、Consistency(一致性)、

                  Isolation(隔离性)和Durability(持久性)的英文缩写。

       原子性(atomicity):事务中的所有操作要么全部提交成功,要么全部失败回滚。

       一致性(consistency):数据库总是从一个一致性状态转换到另一个一致性状态。

       隔离性(isolation):一个事务所做的修改在提交之前对其它事务是不可见的。

       持久性(durability):一旦事务提交,其所做的修改便会永久保存在数据库中。     

 

五、简述三次握手和四次挥手:

       三次握手:

            1. client发送SYN(seq=x)报文 => server(client状态变为SYN_SENT)

            2. server发送ACK(seq=x+1)以及SYN(seq=y)报文 =>client (server状态变为SYN_RECV)

            3. client发送ACK(seq=y+1) => server (client变为ESTABLISHED,服务器收到后也变为ESTABLISHED)   

       四次挥手:

            1. client发送FIN(seq=x) =>server (client变为FIN_WAIT_1)

            2. server先回复ACK(seq=x+1) => client (server只要收到FIN报文就会变为CLOSE_WAIT, client变为FIN_WAIT_2)

            3. server发送完剩余的数据报文后,再发送FIN(seq=y) =>client (server变为LAST_CHECK)

            4. client发送ACK(seq=y+1) => server (client变为TIME_WAIT)

            server收到ACK后直接就关闭closed状态,但client要等2MSL(最大报文生存时间)才会变为closed。

            client的状态转变顺序:established-->fin_wait_1->fin_wait_2->time_wait->closed

            server的状态转变顺序: established-->close_wait->last_ack->closed

        

六、正向代理和反向代理

        

 

国双科技    python开发工程师

一、简述django的一次请求的生命周期(运行上下文)

       1、简略版的请求过程

 

        

 

        2、详细版的请求过程:

 

        总结一下:当有请求到来时,会调用WSGIServer的handle_request方法实例化WSGIRequestHandler

                         然后WSGIRequestHandler在实例化的同时会调用handle方法实例化ServerHandler,

                         并调用其run方法,ServerHandler的run方法会实例化WSGIHandler,WSGIHandler会加载中间件,

                         中间件会对请求进行过滤,过滤方式为:

                                当请求发出时候 -> 经过precess_request -> 进行路由分发,函数匹配到相关url则进行                                                   process_view,否则请求失败->函数(viewfunction)处理完毕

                                ->经过precess_response返回数据 ->假如有异常则执行process_exception

 

        简单明了:WSGIServer -> WSGIRequestHandler -> ServerHandler -> WSGIHandler -> 中间件过滤 

 

二、对称加密和非对称加密的区别

       对称加密:加密和解密使用同一个密钥

       非对称加密:加密用公钥,解密用私钥

 

三、用过什么加密方式?哪种加密性能更好

       1、MD5算法(散列):

            MD5用的是哈希函数,它的典型应用是对一段信息产生信息摘要,以防止被篡改。

            严格来说,MD5不是一种加密算法而是摘要算法。无论是多长的输入,

            MD5 都会输出长度为 128bits 的一个串 (通常用 16 进制 表示为 32 个字符)。

 

       2、SHA1算法(散列):

            SHA1是和MD5一样流行的消息摘要算法,然而SHA1比MD5的安全性更强。

            对于长度小于 2 ^ 64 位的消息,SHA1 会产生一个160位的消息摘要。

            基于 MD5、SHA1 的信息摘要特性以及不可逆 (一般而言),

            可以被应用在检查文件完整性以及数字签名等场景。

 

       3、SHA256(SHA2)算法(散列):

            SHA256会产生一个256位的消息摘要。

            

       3、HMAC算法:

            HMAC 是密钥相关的哈希运算消息认证码,HMAC运算利用哈希算法 (MD5、SHA1 等),

            以一个密钥和一个消息为输入,生成一个消息摘要作为输出。

 

            HMAC发送方和接收方都有key进行计算,而没有这把key的第三方,

            则是无法计算出正确的散列值的,这样就可以 防止数据被篡改。

 

       4、AES/DES/3DES算法(对称):

            AES、DES、3DES都是对称的块加密算法,加解密的过程是可逆的。

 

       5、RSA算法(非对称):

            RSA 加密算法是目前最有影响力的公钥加密算法,并且被普遍认为是目前最优秀的公钥方案 之一。

            RSA 是第一个能同时用于加密和数字签名的算法,它能够抵抗到目前为止已知的所有密码攻击,

            已被 ISO 推荐为公钥数据加密标准。

 

       6、ECC算法(非对称):

            ECC 也是一种 非对称加密算法,主要优势是在某些情况下,它比其他的方法使用更小的密钥,

            比如RSA加密算法,提供 相当的或更高等级 的安全级别。

            不过一个缺点是加密和解密操作的实现比其他机制时间长。

 

四、restful的优缺点

       restful的概念:将URL定义为每一个资源的地址,GET请求方式用来获取资源,

                               POST请求方式用来新建资源(也可以用于更新资源),

                               PUT请求方式用来更新资源,DELETE请求方式用来删除资源

       优点:资源和行为分离,更容易理解,更加规范

       缺点:用PUT和DELETE方式会增加复杂度,并没有带来什么好处

                 面对复杂的业务逻辑,无法抽象为资源的增删改查

 

五、MySQL数据库的底层架构

       MySQL的底层架构如下图所示:

        

        上图中设计的部件介绍:

        1.connectors:与其他编程语言中的sql 语句进行交互

        2.Management Serveices & Utilities: 系统管理和控制工具

        3.Connection Pool (连接池):管理缓冲用户连接,线程处理等需要缓存的需求

        4.SQL Interface (SQL接口):接受用户的SQL命令,并且返回用户需要查询的结果。

                                                    比如select from就是调用SQL Interface

        5.Parser (解析器):SQL命令传递到解析器的时候会被解析器验证和解析。

        6.Optimizer (查询优化器):SQL语句在查询之前会使用查询优化器对查询进行优化

                                                   (产生多种执行计划,最终数据库会选择最优化的方案去执行,尽快返会结果) 

                                                   他使用的是“选取-投影-联接”策略进行查询。

        7.Cache和Buffer (查询缓存):如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。

        8.Engine (存储引擎):存储引擎是MySql中具体的与文件打交道的子系统。

 

        一条SQL语句执行的全过程:

        connectors交互 -> 暂存在Connection Pool中,由Management Serveices 管理 -> 

        转到SQL Interface -> 查询Cache中是否有匹配的结果,若有则直接返回该结果 -> 

        转到Parser判断SQL语句是否正确 -> 转到Optimizer选择最优的执行方案 ->

        转到Engine处理,与后端的存储设备交互后获取到对应的数据返回

 

六、MongoDB的使用

       首先需要明确MongoDB中的一些概念:

              1、文档:文档是MongoDB中存储数据的基本单位,结构是一组键值对

              2、集合:集合就是MongoDB中的文档组,类似于MySQL中的表格。

              3、MongoDB对文档的增删改查:

                            增:db.集合名称.insert(document)

                            删:db.集合名称.remove(,{justOne: })

                            改:db.集合名称.update( ,,{multi: })    

                            查:db.集合名称.find()

 

八、python的垃圾回收机制

       python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略。

 

       引用计数的原理:每个对象维护一个ob_ref字段,用来记录该对象当前被引用的次数,

                                  每当新的引用指向该对象时,它的引用计数ob_ref加1,

                                  每当该对象的引用失效时计数ob_ref减1,一旦对象的引用计数为0,

                                  该对象立即被回收,对象占用的内存空间将被释放。

 

       标记清除的原理:标记清除分为两个阶段:第一阶段是标记阶段,把所有的『活动对象』打上标记,

                                  第二阶段是把那些没有标记的对象『非活动对象』进行回收。

       

       分代收集的原理:分代回收是一种以空间换时间的操作方式,

                                  Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,

                                  Python将内存分为了3“代“,分别为年轻代(第0代)、中年代(第1代)、

                                  老年代(第2代)他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。

                                  新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,

                                  Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,

                                  而那些不会回收的对象就会被移到中年代去,依此类推,

                                  老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。

 

九、分布式架构

       主要是使用Celery框架

 

十、网站的安全证书(SSL)

       网站安全证书又叫SSL证书,是数字证书的一种。

       网站通过安装SSL证书,在客户端浏览器和Web服务器之间建立一条SSL安全通道,

       从而实现数据信息在客户端和服务器之间的加密传输。

       可以有效防止数据信息的泄露。保证了双方传递信息的安全性,

       而且用户可以通过服务器证书验证他所访问的网站是否是真实可靠。

       网站所有者需要向CA(权威证书颁发机构)申请安全证书

 

十一、MySQL数据库存储的数据结构

       常用的数据结构为B树和B+树

        

十二、堆和栈的区别

        堆和栈的定义:

               堆,队列优先,先进先出 

               栈,先进后出

        堆和栈的区别: 

              1、堆栈空间分配

               栈(操作系统):由操作系统自动分配释放,存放函数的参数值,局部变量的值等。

               堆(操作系统):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,

                                              存储的是实体

          2、堆栈缓存方式

               栈使用的是一级缓存,他们通常都是被调用时处于存储空间中,调用完毕立即释放。

               堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定。

                    所以调用这些对象的速度要相对来得低一些。

          3、堆栈数据结构区别

               堆(数据结构):堆可以被看成是一棵树,如:堆排序。

               栈(数据结构):一种先进后出的数据结构。

 

十三、简述docker

        Docker是一个开源的应用容器引擎,基于Go语言 并遵从Apache2.0协议开源。

        Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,

        然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

        容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),

        更重要的是容器性能开销极低。

 

十四、如何实现单元测试

         主要使用pytest进行单元测试,pytest是一个无数人推荐并在使用的Python单元测试框架,

         它使用起来非常简单,只要你的方法名以 test 开头就可以,

         你可以和需要测试的方法放在一起,亦或是新建一个文件来专门整理单元测试,都可以。

 

         使用:在PyCharm中只要你将默认的单元测试驱动改成pytest,

                   就可以在任意test开头的方法上通过右键菜单运行或者调试这个测试案例,非常方便。

        

 

        

 

腾讯外包    Python开发工程师

一、迭代器和生成器的区别

       首先要明确几个概念:

              1.容器(container):

                        容器是一种把多个元素组织在一起的数据结构,

                        可以用in, not in关键字判断元素是否包含在容器中

                        常见的容器对象有list,set,tuples

 

              2.可迭代对象(iterable):

                        只要是可以返回一个迭代器的对象都是可迭代对象

 

              3.迭代器(iterator):

                        迭代器是实现了工厂模式的对象,他能在你调用next()方法的时候返回容器中的下一个值,

                        任何实现了__iter__和__next__方法的对象都是迭代器,

                        __iter__返回迭代器自身,__next__返回容器中的下一个值,

                        如果容器中没有更多元素了,则抛出StopIteration异常

 

                        有很多关于迭代器的例子,比如itertools函数返回的都是迭代器对象。

            

              4.生成器(generator):

                        生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。

                        它不需要再像上面的类一样写__iter__()和__next__()方法了,

                        只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),

                        因此任何生成器也是以一种懒加载的模式生成值。

 

              总结:迭代器和生成器的区别是迭代器是实现了__iter__和__next__方法的对象,

                        而生成器是一种特殊的迭代器,它的返回值不是通过return而是用yield

                        

二、写一个装饰器获取函数运行时间

              1、装饰器的概念:

                   装饰器本质上是一个Python函数。它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,

                   装饰器的返回值也是一个函数对象。

              2、代码实现:

                    

 

三、返回数组中第K大的数的算法

        

     

 

四、MySQL聚合查询的SQL语句

 

五、HTTP常用的状态码

        100:继续发送请求

 

        101:转换协议

 

        102:继续处理

 

        200:请求成功

 

        201:请求完成

 

        202:请求阻塞等待

 

        204:服务器端已经实现了请求,但是没有返回新的信息。

 

        301:重定向到分配的URL

 

        302:重定向到临时的URL

 

        304:请求的资源未更新

 

        400:非法请求

 

        401:未授权

 

        403:禁止

 

        404:没有找到

 

        500:服务器内部错误

 

        501:服务器无法识别

 

        502:错误网关

 

        503:服务出错

 

六、压缩文件的Linux命令

       tar -zcvf 打包后生成的文件名全路径 要打包的目录

 

七、二叉树的前序遍历、中序遍历和后序遍历

 

 

 

你可能感兴趣的:(Python)