一.Python基础

  1.Python语言特性:

    动态型(运行期确定类型,静态型是编译型确定类型),强类型(不发生隐式转换,弱类型,如PHP,JavaScript就会发生隐患式转换

  2.Python作为后端语言的优缺点:

    优点:

      胶水语言,轮子多,应用广泛;语言灵活,生产力高

    缺点:

      性能问题,代码维护问题,python2/3不兼容问题

  3.鸭子类型:

    “当一只鸟走起来像鸭子,游泳像鸭子,叫起来像鸭子,那么这只鸟就能被称为鸭子”

    关注点在对象的行为,而不是类型;

    如file,StringIO,socket都支持read/write方法(file类型)

    定义了__iter__就可以用for迭代

  4.monkey patch(猴子补丁):

    就是运行时替换

    4.1比如gevent需要修改内置的socket和select:

Python面试知识点小结

 

    4.2自己写的猴子补丁:

      Python面试知识点小结

    5.is和==:

    is是判断是否为同一个对象(id内存地址是否相同),==是判断值是否相同

  6.列表,生成器,字典推导:

Python面试知识点小结

  7.Python之禅:

    Tim Peters编写的关于Python编程的规则;

    import this查看,编程拿不准可以查看:

Python面试知识点小结

                

优美胜于丑陋(Python 以编写优美的代码为目标)

明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)

简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)

复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)

扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)

间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)

可读性很重要(优美的代码是可读的)

即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)

不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)

当存在多种可能,不要尝试去猜测

而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)

虽然这并不容易,因为你不是 Python 之父(这里的 Dutch 是指 Guido )

做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)

如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)

命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)

  8.Python2/3的差异:

    Python3改进:

      print改为函数,可以指定sep参数;

      编码问题:Python3不再有Unicode对象,默认str就是Unicode

      除法变化,Python3除号(/)返回浮点数,Python2向下取整,Python3向下取整为(//)

      类型注解(type hint)。帮助IDE实现类型检查;

Python面试知识点小结

主要是提示作用,检查可以用mypy包

      优化的super()函数方便直接调用父类函数;

      高级解包操作:a,b,*rest=range(10)

 

Python面试知识点小结

      限定关键字参数(Keyword only arguments),防止把数据搞混

Python面试知识点小结

 

      Chained exceptions。Python3重新抛出异常不会丢失栈信息(有利于排错),raise from保留栈信息(raise NotImplementedError("haha") from OSError)

      一切返回迭代器range,zip,map,dict.values,etc(节省内存)

Python面试知识点小结

      生成的pyc文件统一放到__pyache__;

        一些内置库的修改,如urllib,selector等;

      性能优化等

    Python新增:

      yield from链接子生成器;

      asyncio内置库,async/await原生协程支持异步编程;

      新的内置库enum(枚举),mock(单测),asyncio(异步),ipaddress(处理ip地址),concurent.futures等

     Python/2/3兼容工具:

      six模块;2to3等工具转换代码;__future__

  9. Python函数常考题:

    Python如何传递参数:

      传递值还是引用?都不是,唯一支持的参数传递是共享传参;

      Call by Object(Call by Object Reference or Call by Sharing)

      共享传参,函数形参获得实参种各个引用的副本      

Python面试知识点小结

     Python面试知识点小结

ll指向[1,2,3],l也指向[1,2,3],后又指向[],所以ll仍为[1,2,3],l为[]

Python面试知识点小结

默认参数只计算一次

    Python可变,不可变对象:

      不可变对象:bool/int/float.str/frozenset;

      可变对象:list/set/dict

    Python *args,**kwargs:

      用来处理可变参数,*args会被打包成tuple,**kwargs会打包成dict

  10.Python异常处理机制:

    什么是Python的异常:

      Python使用异常处理错误(有些语言使用错误码,如C)

      BaseException(最低层异常)

      SystemExit,Timeout(超时),KeyboradInterrupt(ctrl+c),GeneratorExit(生成器退出异常),继承Exception(继承BaseException)

    使用异常常见场景:

      网络超时(超时,资源错误);

      资源问题(权限问题,资源不存在)

      代码逻辑(越界访问,KeyError等)       

    如何处理:

try:
#fun #可能抛出异常的代码块
except (Exception1,Exception2) as e: #可以捕获多个异常并处理
#异常处理的代码
else:
#pass #异常没有发生的时候代码逻辑
finally:
pass #无论异常有没有发生都会执行的代码,一般处理资源的关闭和释放

     如何自定义异常,作用:

      通过继承Exception实现定义异常(为什么不是BaseException,ctrl+c不能结束,BaseException是所有异常的基类,KeyboradInterrupt和SystemExit,GeneratorExit,Exception都继承于它,如果继承BaseException,可能捕获不到一些异常。)

      给异常加一些附加信息;

      处理一些业务相关的特定异常(raise MyException)

  10.Python性能分析与优化,GIL常考题:

    GIL(Global Interpreter Lock):全局解释器锁

      Cpython解释器的内存管理并不是线程安全的;

      保护多线程情况下对Python对象的访问;

      Cpython使用简单的锁机制避免多个线程同时执行字节码。

    GIL的影响:

      限制了程序的多核执行:

        同一个时间只能有一个线程执行字节码;

        CPU密集程序难以利用多核优势;

        IO期间会释放GIL,对IO密集程序影响不大

    如何规避GIL影响:

      CPU密集可以用多进程+进程池;

      IO密集使用多线程/协程

      cython扩展

    Python中什么操作才是原子的?一步到位执行完:

      一个操作如果一个字节码指令可以完成就是原子的;

      原子的是可以保证线程安全的;

      使用dis操作来分析字节码。

Python面试知识点小结

    如何剖析程序性能:

      使用profile工具(内置或第三方)

        二八定律:大部分时间耗时在少量代码上;

        内置的profile/cprofile等工具;

        使用pyflame(uber开源)的火焰图工具

    服务端性能优化措施:

      web应用一般语言不会成为瓶颈:

          数据结构与算法优化;

        数据库层:索引优化,慢查询消除,批量操作减少IO,NoSql

        网络IO:批量操作,pipeline操作减少IO

        缓存:使用内存数据库 redis。memcached

        异步:asyncio,celery

        并发:gevent/多线程

  11.生成器和协程:

    生成器:

      生成器就是可以生成值的函数;

      当一个函数里有了yield关键字就成了生成器;

      生成器可以挂起并保持当前执行状态

    基于生成器的协程:

      Python3之前没有原生的协程,只有基于生成器的协程

        pep342增强生成器功能;

        生成器可以通过yield暂停执行和产出数据;

        同时支持end()向生成器发送数据和throw()向生成器抛异常

    

    协程注意点:

      协程使用send(None)或者next(coroutine)来预激(prime)才能启动;

      在yield出协程会暂停执行;

      单独的yield value会产出值给调用方;

      可以通过coroutine.send(value)来给协程发送值,发送的值会赋值给yield表达式左边的变量value=yield

      协程执行完成后(没有遇到下一个yield语句)会抛出StopIteration异常

      避免每次都使用send预激它(from functool import wraps)@wraps装饰器向前执行一个yield表达式,预激

      Python3.5引入async/await支持原生协程

  12.Python单元测试:

    什么是单元测试:

      针对程序模块进行正确性检验;

      一个函数,一个类进行验证;

      自底向上保证程序正确性

    为什么要写单元测试:

      三无代码不可取(无文档,无注释,无单测)

      保证代码逻辑的正确性(甚至有些采用测试驱动开发(TDD))

      单测影响设计,易测的代码往往是高类聚低耦合的;

      回归测试,防止一处修改整个服务不可用

    单元测试库:

      nose/pytest较为常用;

      mock模块用来模拟替换网络请求等

       coverage统计测试覆盖率

    Python深拷贝和浅拷贝:

      深拷贝,包含对象里面的自对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变。

      浅拷贝相当于拷贝了对象的引用(在python中,对象赋值实际上是对象的引用。当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用)

    Python创建二维数组:

      https://www.cnblogs.com/woshare/p/5823303.html

二.算法和数据结构:  

  1.常用的内置算法结构:

    sorted;

    dict/list/set/tuple.... 

Python面试知识点小结

    collections中常用模块:

      namedtuple:让tuple属性可读(赋予名字)

Python面试知识点小结

      deque:双端队列(可以在队列前后操作,方便实现queue/statck)

Python面试知识点小结

      Counter:实现计数的功能

Python面试知识点小结

      OrderDict:可以记住key第一次进入的位置(有序的)

Python面试知识点小结

       defaultdict():键不存在时不会报错(带有默认值的字典)

Python面试知识点小结

      dict低层使用的hash表:

        为了支持快速查找使用了哈希表作为低层结构;

        哈希表平均查找复杂度为O(1);

        CPython解释器使用二次探查解决哈希冲突问题(如何解决哈希冲突,哈希扩容)

      list vs tuple:

        都是线性结构,支持下标访问;

        list是可变对象,tuple是保存的引用不可变(指的是没法替换掉这个对象,但是如果对像本身是一个可变对象,是可以修改这个引用指向的可变对象的);  

       Python面试知识点小结

        list没法作为字典的key,tuple可以(可变对象不可hash)

      LRUCache:

        Least-Recently-Used替换最少使用的对象

        缓存剔除策略,当缓存空间不够用的时候需要一种方式剔除key

        常见的有LRU,LFU

        LRU通过使用一个循环双端队列不断把最新访问的key放到表头实现

        实现:

          字典利用缓存,循环双端链表用来记录访问顺序:

            利用Python内置的dict+collections.OrderdDict实现;

            dict用来当作k/v键值对的缓存;

            OrderedDict用来实现最近访问的key

        实现代码:     

 1 from collections import OrderedDict
 2 
 3 class LRUCathe:
 4         def __init__(self,capacity=120):
 5             self.od=OrderedDict()
 6             self.capacity=capacity
 7         
 8         def get(self,key):
 9             if key in self.od:
10                 val=self.od[key]
11                 self.od.move_to_end(key)
12                 return val
13             else:
14                 return -1
15         # 更新k/v
16         def put(self,key,value):
17             if key in self.od:
18                 del self.od[key]
19                 #更新key到表头
20                 self.od[key]=value
21             else:
22                 self.od[key]=value
23                 #判断当前容量是否满了
24                 if len(self.od)>self.capacity:
25                     self.od.popitem(last=False)

 

    2.算法常考题:

      排序,查找等。。。。

      排序的稳定性:

        相同大小的元素排序之后保持相对的位置不变,就是稳定的。稳定性对于排序一个复杂的结构,并且保持原有排序才有意义。

      快排:(分治法)

        选择基准分割数组为两个字数组,小于基准和大于基准的;

        对两个子数组分别快排;

        合并结果。

 1 '''快速排序:
 2     时间平均复杂度:O(nlog2n)
 3     最好情况:O(nlog2n)
 4     最坏:O(n^2)
 5     空间复杂度:O(nlog2n)
 6     排序方式:内部排序
 7     稳定性:不稳定
 8     '''
 9 def quicksort(arr):
10     if len(arr)<2:
11         return arr
12 
13     pivot_index=0
14     pivot=arr[pivot_index]
15     less_pivot=[i for i in arr[pivot_index+1:] if i <=pivot]
16     great_pivot=[i for i in arr[pivot_index+1:] if i > pivot]
17     return quicksort(less_pivot)+[pivot]+quicksort(great_pivot)
18 print(quicksort([3,4,5,6]))
View Code

相关文章: