1. 现有字典 d={ ‘a’ :24, ’g’ :52, ’l’ :12, ’k’ :33} 请按字典中的 e value 值进行排序?
In [3]: sorted(d.items(),key = lambda x:x[1])
Out[3]: [(‘l’, 12), (‘a’, 24), (‘k’, 33), (‘g’, 52)]
解:
In [4]: d.items()
Out[4]: dict_items([(‘a’, 24), (‘k’, 33), (‘g’, 52), (‘l’, 12)]
items() 函数以列表返回可遍历的(键, 值) 元组数组。
In [5]: sorted(d.items())
Out[5]: [(‘a’, 24), (‘g’, 52), (‘k’, 33), (‘l’, 12)]
sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
sorted 语法:
sorted(iterable, key=None, reverse=False)
2. map 函数和 reduce 函数的区别?
①从参数方面来讲:
map()包含两个参数,第一个参数是一个函数,第二个是序列(列表或
元组)。其中,函数(即 map 的第一个参数位置的函数)可以接收一个或多
个参数。
reduce() 第一个参数是函数,第二个是 序列(列表或元组)。但是,
其函数必须接收两个参数。
②从对传进去的数值作用来讲:
map()是将传入的函数依次作用到序列的每个元素,每个元素都是独自被
函数“作用”一次;(请看下面的例子)
reduce()是将传入的函数作用在序列的第一个元素得到结果后,把这个
结果继续与下一个元素作用(累积计算)
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
map()函数可以将list所有数字转为字符串:
map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’]
3. python 的魔法 方法
魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重
载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所
调用,你可以定义自己想要的行为,而这一切都是自动发生的。它们经常是
两个下划线包围来命名的(比如 init,lt),Python 的魔法方法
是非常强大的,所以了解其使用方法也变得尤为重要!
init 构造器,当一个实例被创建的时候初始化的方法。但是它并不
是实例化调用的第一个方法。
new才是实例化对象调用的第一个方法,它只取下 cls 参数,并把
其他参数传给 init。 new很少使用,但是也有它适合的场景,尤其
是当类继承自一个像元组或者字符串这样不经常改变的类型的时候。
call 允许一个类的实例像函数一样被调用
getitem 定义获取容器中指定元素的行为,相当于 self[key]
getattr 定义当用户试图访问一个不存在属性的时候的行为
setattr 定义当一个属性被设置的时候的行为
getattribute 定义当一个属性被访问的时候的行为
4. 求输出结果
def num():
return [lambda x:i*x for i in range(4)]
print (m(2) for m in num())
结果:[6, 6, 6, 6]
匿名函数lambda [形参列表]:表达式(用来处理返回值)
列表推导式:
a = [x for x in range(4)]
可理解为:
a = []
for x in range(4):
a.append(x)
5. 对缺省参数的理解?
缺省参数指在调用函数的时候没有传入参数的情况下,调用默认的参数,
在调用函数的同时赋值时,所传入的参数会替代默认参数
**6. 对装饰器的理解,并写出一个计时器记录方法执行性能的装饰
器。**
装饰器本质上是一个 Python 函数,它可以让其他函数在不需要做任何代
码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象
7. 什么是线程安全,什么是互斥锁?
每个对象都对应于一个可称为” 互斥锁” 的标记,这个标记用来保证在
任一时刻,只能有一个线程访问该对象。
同一个进程中的多线程之间是共享系统资源的,多个线程同时对一个对
象进行操作,一个线程操作尚未结束,另一个线程已经对其进行操作,导致最
终结果出现错误,此时需要对被操作对象添加互斥锁,保证每个线程对该对象
的操作都得到正确的结果
8. 什么单例模式,其应用场景都有哪些?
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实
例,这个类称为单例类,单例模式是一种对象创建型模式。
Windows 的 Task Manager(任务管理器)、Recycle Bin(回收站)、网
站计数器
单例模式应用的场景一般发现在以下条件下:
(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如
上述中的日志文件,应用配置。
(2)控制资源的情况下,方便资源之间的互相通信。如线程池等。
9. 递归函数停止的条件?
递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件
判断,根据判断的结果选择是继续调用自身,还是 return;返回终止递归。
终止的条件:
1.判断递归的次数是否达到某一限定值
2. 判断运算的结果是否达到某个范围等,根据设计的目的来选择
10. python 是强语言还是弱语言
Python 是强类型的动态脚本语言 。
强类型:不允许不同类型相加,需要类型转换,
动态:不使用显示数据类型声明,且确定一个变量的类型是在第一次给
它赋值的时候
脚本语言:一般也是解释型语言,运行代码只需要一个解释器,不需要
编译
11.python 的内存管理机制及调优手段?
内存管理机制:引用计数、垃圾回收、内存池
引用计数
引用计数是一种非常高效的内存管理手段, 当一个 Python 对象被引 用
时其引用计数增加 1, 当其不再被一个变量引用时则计数减 1. 当引用计数
等于 0 时对象被删除.
垃圾回收
1. 引用计数
引用计数也是一种垃圾收集机制,而且也是一种最直观,最简单的垃圾
收集技术。当 Python 的某个对象的引用计数降为 0 时,说明没有任何引用指
向该对象,该对象就成为要被回收的垃圾了。比如某个新建对象,它被分配
给某个引用,对象的引用计数变为 1。如果引用被删除,对象的引用计数为 0,
那么该对象就可以被垃圾回收。
不过如果出现循环引用的话,引用计数机制就不再起有效的作用了
2. 标记清除
如果两个对象的引用计数都为 1,但是仅仅存在他们之间的循环引用,
那么这两个对象都是需要被回收的,也就是说,它们的引用计数虽然表现为
非 0,但实际上有效的引用计数为 0。所以先将循环引用摘掉,就会得出这两
个对象的有效计数。
3. 分代回收
从前面“标记-清除”这样的垃圾收集机制来看,这种垃圾收集机制所带
来的额外操作实际上与系统中总的内存块的数量是相关的,当需要回收的内
存块越多时,垃圾检测带来的额外操作就越多,而垃圾回收带来的额外操作
就越少;反之,当需回收的内存块越少时,垃圾检测就将比垃圾回收带来更
少的额外操作。
举个 例子:
当某些内存块 M 经过了 3 次垃圾收集的清洗之后还存活时,我们就将内存
块 M 划到一个集合 A 中去,而新分配的内存都划分到集合 B 中去。当垃圾收
集开始工作时,大多数情况都只对集合 B 进行垃圾回收,而对集合 A 进行垃
圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内
存少了,效率自然就提高了。在这个过程中,集合 B 中的某些内存块由于存
活时间长而会被转移到集合 A 中,当然,集合 A 中实际上也存在一些垃圾,
这些垃圾的回收会因为这种分代的机制而被延迟。
内存池
1.Python 的内存机制呈现金字塔形状,-1,-2 层主要有操作系统进行操作;
2.第 0 层是 C 中的 malloc,free 等内存分配和释放函数进行操作;
3.第1 层和第2 层是内存池,有Python的接口函数PyMem_Malloc 函数实现,
当对象小于 256K 时有该层直接分配内存;
4.第 3 层是最上层,也就是我们对 Python 对象的直接操作;
Python 在运行期间会大量地执行 malloc 和 free 的操作,频繁地在用户
态和核心态之间进行切换,这将严重影响 Python 的执行效率。为了加速
Python 的执行效率,Python 引入了一个内存池机制,用于管理对小块内存的
申请和释放。
Python 内部默认的小块内存与大块内存的分界点定在 256 个字节,当申
请的内存小于 256 字节时,PyObject_Malloc 会在内存池中申请内存;当申
请的内存大于 256 字节时,PyObject_Malloc 的行为将蜕化为 malloc 的行为。
当然,通过修改 Python 源代码,我们可以改变这个默认值,从而改变 Python
的默认内存管理行为。
调优手段(了解)
1.手动垃圾回收
2.调高垃圾回收阈值
3.避免循环引用(手动解循环引用和使用弱引用)
12. 生成器、迭代器的区别?
在 Python 中,一边循环一边计算的机制,称为生成器:generator,生
成器是可以迭代对象,但是生成器可以通过 send 传值返回到前面;
注意点:
1、每次调用next方法会执行到yield,并返回yield后面的数据
2、只要在def的函数中有yield关键字,这个函数就被转换为了生成器
3、再次调用next会从上一次停止的代码继续执行
4、return会导致生成器抛出StopIteration异常,return返回的数据会作为异常的描述信息
5、next( )函数也能取出生成器数据
6、不同的生成器对象,是彼此独立的
生成器.send( )
1、yield可以使用send发送来的数据执行一些条件判断
2、如果在获取生成器第一个数字的时候使用send,则必须传递None
3、send会激活生成器,并传递一个值给yield
yield关键字
1、保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起
2、将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结
束。迭代器只能往前不会后退
迭代器是一个可以记住遍历的位置的对象
可迭代对象:
定义:可以被for循环迭代的对象
都有iter方法,这个方法必须返回一个迭代器对象
可迭代对象能够被for循环处理是因为有迭代器
验证可迭代对象:
isinstance(对象,Iterable)
iter( ) 可以从可迭代对象中获取迭代器
迭代器对象:
定义:由可迭代对象提供,每一次for循环可以获取遍历位置的对象
每次for循环重新开始的时候,会产生新的迭代器对象
必定同时又有iter和next方法
验证迭代器对象:
isinstance(对象,Iterator)
13. 对不定长参数的理解?
不定长参数有两种:*args 和**kwargs;
*args:是位置参数,用来将参数打包成 tuple 给函数体调用
**kwargs:是关键字参数,打包关键字参数成 dict 给函数体调用在定义
函数的时候不确定要传入的参数个数会有多少个的时候就可以使用不定长参
数作为形参
**14. 什么是 lambda 函数?它有什么好处?写一个匿名函数求两个
数的和。**
lambda 函数是匿名函数;使用 lambda 函数能创建小型匿名函数。这种
函数得名于省略了用 def 声明函数的标准步骤;
f = lambda x,y:x+y
print(f(2017,2018))
15. 写一个列表生成式,例: : 产生一个公差为 1 的等差数列
print([x for x in range(10)])
16. 解释一下什么是闭包
在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那
么将这个函数以及用到的一些变量称之为闭包
17. 解释一下什么是锁,有哪几种锁? ?
锁(Lock)是 python 提供的对线程控制的对象
有互斥锁、可重入锁、死锁
18. 什么是死锁以及怎么解决? ?
死锁:在线程间共享多个资源的时候,如果两个线程分别占有一部分资
源并且同时等待对方的资源,就会造成死锁
给互斥锁添加超时时间
程序设计时要尽量避免(银行家算法)
19. 什么是僵尸进程和孤儿进程, , 怎么避免僵尸进程? ?
孤儿进程:父进程退出,子进程还在运行的这些子进程都是孤儿进程,
孤儿进程将被 init 进程(进程号为 1)所收养,并由 init 进程对它们完成状
态收集工作
僵尸进程:进程使用 fork 创建子进程,如果子进程退出,而父进程并没
有调用 wait 或 waitpid 获取子进程的状态信息,那么子进程的进程描述符仍
然保存在系统中的这些进程是僵尸进程
避免僵尸进程的方法:
1.fork 两次用孙子进程去完成子进程的任务
2.用 wait()函数使父进程阻塞
3.使用信号量,在 signal handler 中调用 waitpid,这样父进程不用阻塞
20. 谈一下什么是解释性语言, , 什么是编译性语言? ?
计算机不能直接理解高级语言,只能直接理解机器语言,所以必须要把
高级语言翻译成机器语言,计算机才能执行高级语言编写的程序
解释性语言在运行程序的时候才翻译,解释性语言在运行程序的时候才翻译
编译型语言写的程序执行之前,需要一个专门的编译过程,把程序编译
成为机器语言的文件
21. 捕获异常机制,在 except 中return 后还会不会执行
finally 中的代码?怎么抛出自己处理不了的异常?
会继续处理 finally 中的代码;
用 raise 方法可以手动抛出异常
22. Python 中有日志吗? ? 怎么使用? ?
有日志;
python 自带 logging 模块,调用 logging.basicConfig()方法,配置需
要的日志等级和相应的参数,python 解释器会按照配置的参数生成相应的日志
23. 代码中要修改不可变数据会出现什么问题? ? 抛出什么异常? ?
代码不会正常运行,抛出异常 TypeError 异常
24. python 中的进程与线程的使用场景? ?
多进程适合在 CPU 密集型操作(cpu 操作指令比较多,如位数多的浮点运
算)
多线程适合在 IO 密集型操作(读写数据操作较多的,比如爬虫)
1、进程是资源分配的单位
2、线程是操作系统调度的单位
3、进程切换需要的资源很最大,效率很低
4、线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)
5、协程切换任务资源很小,效率高
6、多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发
25. 为什么函数名字可以当做参数用?
python 中一切皆对象,函数名是函数在内存中的空间,也是一个对象
26.linux 的基本命令(怎么区分一个文件还是文件夹)
ls -F 在显示名称的时候会在文件夹后添加“/”,在文件后面加“*”
得到的结果,如果首字母是d则为文件夹,如果为-则为文件
27. 日志以什么格式,存放在哪里?
日志以文本可以存储在“/var/log/”目录下后缀名为.log
28. 回调函数,如何通信的? ?
回调函数是把函数的指针(地址)作为参数传递给另一个函数,将整个函
数当作一个对象,赋值给调用的函数
29. 浮点数如何进行比较大小? ?
浮点数的表示是不精确的,不能直接比较两个数是否完全相等,一般都
是在允许的某个范围内认为像个浮点数相等,如有两个浮点数 a,b,允许的
误差范 围为 1e-6,则 abs(a-b)<=1e-6,即可认为 a 和 b 相等
python3.5 的 math 模块新增一个 isclose 函数用来判断两个浮点数的值
是否接近或相等
import math
print(math.isclose(1.25,1.25))# 返回一个布尔值 True
print(math.isclose(2.1,2.2,rel_tol=0.1))
参数:
a,b:两个需要比较的浮点数;
rel_tol: 相对于输入值的大小,被认为是“接近”的最大差异;
abs_tol: 无论输入值的大小,被认为“接近”的最大差异
30. 线程是并发还是并行,进程是并发还是并行?
线程是并发,进程是并行;进程之间相互独立,是系统分配资源的最小
单位,同一个线程中的所有线程共享资源
31. 什么是可变、不可变?元组里添加字典,会改变 id 吗?
可变不可变指的是内存中的值是否可以被改变,不可变类型指的是对象
所在内存块里面的值不可以改变,有数值、字符串、元组;可变类型则是可
以改变,主要有列表、字典
元组的顶层元素中包含可变类型,在可变类型中修改或添加字典 id 不会
改变
32. init 和 news 的区别?
init 在对象创建后,对对象进行初始化
new 是在对象创建之前创建一个对象,并将该对象返回给 init
33. 存入字典里的数据有没有先后排序?
存入的数据不会自动排序,可以使用 sort 函数对字典进行排序