目录
前言
一、Python 的内存管理机制及调优手段?
二、什么是 lambda 函数,有什么好处?
三、你对装饰器的理解?
四、Python 排序算法的理解
五、Python常见的魔法方法
在面试自动化测试、测试开发等职位时,经常会问到Python高阶编程相关的问题,以下就介绍Python中一些常见的高阶的面试题,果断安排上惹了。
Python内存管理机制:引用计数、垃圾回收、内存池。
1、引用计数
引用计数是一种非常高效的内存管理手段, 当一个 Python 对象被引用时其引用计数增加 1, 当其不再被一个变量引用时则计数减 1, 当引用计数等于 0 时对象被删除。
2、垃圾回收
(1) 引用计数
引用计数也是一种垃圾收集机制,而且也是一种最直观,最简单的垃圾收集技术。当 Python 的某个对象的引用计数降为 0 时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。比如某个新建对象,它被分配给某个引用,对象的引用计数变为 1。如果引用被删除,对象的引用计数为 0, 那么该对象就可以被垃圾回收。不过如果出现循环引用的话,引用计数机制就不再起有效的作用了。
(2) 标记清除
如果两个对象的引用计数都为 1,但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被回收的,也就是说,它们的引用计数虽然表现为非 0,但实际上有效的引用计数为 0。所以先将循环引用摘掉,就会得出这两个对象的有效计数。
(3) 分代回收
分代回收是一种以空间换时间的操作方式,Python 将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python 将内存分为了 3“代”,分别为年轻代(第 0 代)、中年代(第 1 代)、老年代(第 2 代),他们对应的是 3 个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。
新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python 垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。
同时,分代回收是建立在标记清除技术基础之上。分代回收同样作为 Python 的辅助垃圾收集技术处理那些容器对象。
3、内存池
Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效 率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
4、调优手段
1、手动垃圾回收。对Python的垃圾回收进行调优的一个最简单的手段便是关闭自动回收, 根据情况手动触发。
2、调高垃圾回收阈值。调高阈值的方法能在一定程度上避免内存溢出的问题(但不能完全避免), 同时可能减少可观的垃圾回收开销. 根据具体项目 的不同, 甚至是程序输入的不同, 合适的阈值也不同. 因此需要反复测试找到一个合适的阈值。
3、避免循环引用。使用良好的编程习惯尽可能的避免循环引用. 两种常见的手段: 手动解循环引用和使用弱引用。
lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数。
lambda 函数好处:
1、lambda 函数比较轻便,即用即扔,很适合需要完成一项功能,但是此功能只在此一处使用, 连名字都很随意的情况下;
2、匿名函数,一般用来给 filter, map 这样的函数式编程服务;
3、作为回调函数,传递给某些应用,比如消息处理。
举个例子,提取列表中的偶数。
装饰器本质上是一个Python函数,它可以让已有的函数不做任何改动的情况下增加功能。非常适合有切面需求的场景,比如权限校验,日志记录和性能测试等等。如果你想要执行某个函数前记录日志或者记录时间来统计性能,又不想改动这个函数,就可以通过装饰器来实现。
写出一个计时器装饰器,记录函数的执行时间。
以下主要介绍冒泡排序、选择排序、插入排序、快速排序四种排序算法:
1、冒泡排序
思路:每相邻的两个数进行比较,如果前边的比后边的数大,则交换这两个数,重复操作,这样的话每一趟会确定一个最大值。
2、选择排序
思路:第一趟遍历选择一个最小的数(或最大),放到第一个位置,下一趟遍历继续从列表中找最小的值放到已排序序列的末尾,说白了就是每趟找一个最小的值(或者最大的)~这个算法的关键在于最小数的【位置】。
选择排序时间复杂度为O(n2)。
3、插入排序
思路:将列表分为有序区和无序区,开始的时候有序区只有一个元素,每次从无序区取一个元素插入到有序区内,直到无序区内的元素被取完~这个算法的关键是【有序区已有】的元素和【即将要插入】到有序区的元素。
插入排序的时间复杂度为O(n2)。
4、快速排序
思路:从列表中取一个元素,假如取第一个元素,将这个元素排好后前面的元素都比这个元素小,后面的都比这个元素大,即这个元素所在的位置即是完全排序后该元素的位置,后面递归处理即可~这个算法的关键即【递归】。
快速排序的时间复杂度为O(nlogn)。
Python 的类⾥提供的,两个下划线开始,两个下划线结束的⽅法,就是魔法⽅法,魔法⽅法在恰当的时候就会被激活,⾃动执⾏。 使用Python的魔法方法可以使Python的自由度变得更高,当不需要重写时魔法方法也可以在规定的默认情况下生效,在需要重写时也可以让使用者根据自己的需求来重写部分方法来达到自己的预期。