最新python面试题汇总(二)
接前文:
13 Python中重载
函数重载主要是为了解决两个问题。
1.可变参数类型。
2.可变参数个数。
另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。
14 新式类和旧式类
这篇文章很好的介绍了新式类的特性: http://www.cnblogs.com/btchenguang/archive/2012/09/17/2689146.html
新式类很早在2.2就出现了,所以旧式类完全是兼容的问题,Python3里的类全部都是新式类.这里有一个MRO问题可以了解下(新式类是广度优先,旧式类是深度优先),<Python核心编程>里讲的也很多。
15 __new__和__init__的区别
这个__new__确实很少见到,先做了解吧.
- __new__是一个静态方法,而__init__是一个实例方法.
- __new__方法会返回一个创建的实例,而__init__什么都不返回.
- 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
- 当创建一个新实例时调用__new__,初始化一个实例时用__init__.
ps: __metaclass__是创建类时起作用.所以我们可以分别使用__metaclass__,__new__和__init__来分别在类创建,实例创建和实例初始化的时候做一些小手脚.
16 单例模式
1.使用__new__
方法
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
class MyClass(Singleton):
a = 1
2 共享属性
创建实例时把所有实例的__dict__
指向同一个字典,这样它们具有相同的属性和方法.
class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob
class MyClass2(Borg):
a = 1
3 装饰器版本
def singleton(cls, *args, **kw):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance
@singleton
class MyClass:
a=1
17 import方法
作为python的模块是天然的单例模式
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton()
# to use
from mysingleton import my_singleton
my_singleton.foo()
18 Python中的作用域
Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)。
19 GIL线程全局锁
线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.解决办法就是多进程和下面的协程(协程也只是单CPU,但是能减小切换代价提升性能).
20 协程
简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态.Python里最常见的yield就是协程的思想!
21 闭包
闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。
当一个内嵌函数引用其外部作作用域的变量,我们就会得到一个闭包. 总结一下,创建一个闭包必须满足以下几点:
- 必须有一个内嵌函数
- 内嵌函数必须引用外部函数中的变量
- 外部函数的返回值必须是内嵌函数
闭包就像个空心球一样,你知道外面和里面,但你不知道中间是什么样.
22 lambda函数
其实就是一个匿名函数,为什么叫lambda?因为和后面的函数式编程有关.
23 Python函数式编程
python中函数式编程支持:filter 函数的功能相当于过滤器。调用一个布尔函数bool_func
来迭代遍历每个seq中的元素;返回一个使bool_seq
返回值为true的元素的序列。
a = [1,2,3,4,5,6,7]
b = filter(lambda x: x > 5, a)
print (b)
结果:
[6,7]
map函数是对一个序列的每个项依次执行函数,下面是对一个序列每个项都乘以2:
a = map(lambda x:x*2,[1,2,3])
list(a)
结果:
[2,4,6]
reduce函数是对一个序列的每个项迭代调用函数,下面是求3的阶乘:
reduce(lambda x,y:x*y,range(1,4))
结果:
6
24 Python里的拷贝
引用和copy(),deepcopy()的区别
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象
b = a #赋值,传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝
a.append(5) #修改对象a
a[4].append('c') #修改对象a中的['a', 'b']数组对象
print ('a = ', a)
print ('b = ', b)
print ('c = ', c)
print ('d = ', d)
运行结果:
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]
25 Python垃圾回收机制
Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。
1 引用计数
PyObject是每个对象必有的内容,其中ob_refcnt
就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt
就会增加,当引用它的对象被删除,它的ob_refcnt
就会减少.引用计数为0时,该对象生命就结束了。
优点:
- 简单
- 实时性
缺点:
- 维护引用计数消耗资源
- 循环引用
2 标记-清除机制
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。
3.分代技术
分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。
Python默认定义了三代对象集合,索引数越大,对象存活时间越长。
25 Python里面如何实现tuple和list的转换?
tuple,可以说是不可变的list,访问方式还是通过索引下标的方式。当你明确定义一个tuple时,如果仅有一个元素,必须带有,例如:(1,)。当然,在2.7以后的版本,python里还增加了命名式的tuple!至于有什么用,首先第一点,python的函数可以有多返回值的,而python里,多返回值,就是用tuple来表示,这是用的最广的了。
比如说,你需要定义一个常量的列表,但你又不想使用list,那也可以是tuple,例如:
if a in ('A','B','C'):pass
27 Python的is
is是对比地址,==是对比值
28 read,readline和readlines
- read 读取整个文件
- readline 读取下一行,使用生成器方法
- readlines 读取整个文件到一个迭代器以供我们遍历
29 Python2和3的区别
大部分Python库都同时支持Python 2.7.x和3.x版本的,所以不论选择哪个版本都是可以的。但为了在使用Python时避开某些版本中一些常见的陷阱,或需要移植某个Python项目,主要的区别有以下:
使用__future__模块
print函数
整数除法
Unicode
xrange
触发异常
处理异常
next()函数和.next()方法
For循环变量与全局命名空间泄漏
比较无序类型
使用input()解析输入内容
返回可迭代对象,而不是列表
30 到底什么是Python?
你可以在回答中与其他技术进行对比。下面是一些关键点:
- Python是一种解释型语言。这就是说,与C语言和C的衍生语言不同,Python代码在运行之前不需要编译。其他解释型语言还包括PHP和Ruby。
- Python是动态类型语言,指的是你在声明变量时,不需要说明变量的类型。你可以直接编写类似x=111和x="I'm a string"这样的代码,程序不会报错。
- Python非常适合面向对象的编程(OOP),因为它支持通过组合(composition)与继承(inheritance)的方式定义类(class)。Python中没有访问说明符(access specifier,类似C++中的public和private),这么设计的依据是“大家都是成年人了”。
- 在Python语言中,函数是第一类对象(first-class objects)。这指的是它们可以被指定给变量,函数既能返回函数类型,也可以接受函数作为输入。类(class)也是第一类对象。
- Python代码编写快,但是运行速度比编译语言通常要慢。好在Python允许加入基于C语言编写的扩展,因此我们能够优化代码,消除瓶颈,这点通常是可以实现的。numpy就是一个很好地例子,它的运行速度真的非常快,因为很多算术运算其实并不是通过Python实现的。
- Python用途非常广泛——网络应用,自动化,科学建模,大数据应用,等等。它也常被用作“胶水语言”,帮助其他语言和组件改善运行状况。
- Python让困难的事情变得容易,因此程序员可以专注于算法和数据结构的设计,而不用处理底层的细节。
为什么提这个问题:
如果你应聘的是一个Python开发岗位,你就应该知道这是门什么样的语言,以及它为什么这么酷。以及它哪里不好。
31 你如何管理不同版本的代码?
因为没有版本控制的代码,就像没有杯子的咖啡。有时候我们需要写一些一次性的、可以随手扔掉的脚本,这种情况下不作版本控制没关系。但是如果你面对的是大量的代码,使用版本控制系统是有利的。版本控制能够帮你追踪谁对代码库做了什么操作;发现新引入了什么bug;管理你的软件的不同版本和发行版;在团队成员中分享源代码;部署及其他自动化处理。它能让你回滚到出现问题之前的版本,单凭这点就特别棒了。还有其他的好功能。
32“猴子补丁”(monkey patching)指的是什么?这种做法好吗?
“猴子补丁”就是指,在函数或对象已经定义之后,再去改变它们的行为。
举个例子:
import datetime
datetime.datetime.now = lambda: datetime.datetime(2012, 12, 12)
大部分情况下,这是种很不好的做法 - 因为函数在代码库中的行为最好是都保持一致。打“猴子补丁”的原因可能是为了测试。mock包对实现这个目的很有帮助。
33.介绍一下except的用法和作用?
try…except…except…[else…][finally…]
执行try下的语句,如果引发异常,则执行过程会跳到except语句。对每个except分支顺序尝试执行,如果引发的异常与except中的异常组匹配,执行相应的语句。如果所有的except都不匹配,则异常会传递到下一个调用本代码的最高层try代码中。
try下的语句正常执行,则执行else块代码。如果发生异常,就不会执行如果存在finally语句,最后总是会执行。
上一篇: 有趣的css
推荐阅读
-
所有二本师范大学录取分数线最新汇总(2021年参考)
-
2019 Python最新面试题及答案16道题
-
产品经理面试题汇总(最新面试产品经理十大问题)
-
leetcode 面试题32 (剑指offer)- II. 从上到下打印二叉树 II(python3)
-
leetcode 113 剑指offer 面试题34. 二叉树中和为某一值的路径(python3)
-
剑指offer面试题68 - I. 二叉搜索树的最近公共祖先(python)
-
leetcode 面试题32 - III. 从上到下打印二叉树 III(python3)
-
十进制、二进制、十六进制转换(面试题)原码 补码 python
-
【剑指offer阅读】面试题4:二维数组中的查找 python
-
2020年Python最新面试题(二):Python基础