附答案 | 最强Python面试题之Python进阶题第二弹

本文正在参与【[ 面霸养成记 ] 】 征文活动,一起来聊聊校招的那些事吧,牛客周边和百元京东卡等你来领~

写在之前

大家好呀,我是帅蛋。

这里是帅蛋的【最强Python面试题】系列,面试八股文都在这里呦!!!

周末两天不见,甚是想念,都有牛宝宝来催更了!我赶紧麻溜来更新 Python 进阶面试题第二弹!!

大家久等了!!!虽迟但到,一定要记得点赞收藏呀!!!

顺便提一句,我所有和面试相关的内容都会放在#帅蛋的面试空间# 中,大家可以关注下这个话题~

我会尽我最大的努力帮助到大家哒!!!

主要内容

这些面试题是我结合自己的经验整理的,主要就是下面这 5 个专题:

  • Python 基础面试题
  • Python 进阶
  • Python 后台开发
  • 爬虫
  • 机器学习

已完成

Python 基础题

正在更新

Python 进阶题

对每道面试题我都会附带详细的答案,有些我觉得重要的内容会详细讲解,虽然是面试八股文,我还是希望大家不是只“知其然”,更得“知其所以然”

关于更新频率,每天我会更新 10 道题左右,总共会有差不多 200 道。

无论是准备面试还是自己学习,这份面试题绝对值得你去看,去学习。

大家可以关注我,再关注我,使劲关注我,不要错过每天的更新~

以下是正文

Python 进阶面试题第二弹正式开始,大家一定要记得点赞收藏,一起加油!

1、什么是断言?应用场景?

assert断言——声明其布尔值必须为真判定,发生异常则为假。

info = {}
info['name'] = 'egon'
info['age'] = 18

# 用assert取代上述代码:
assert ('name' in info) and ('age' in info)

设置一个断言目的就是要求必须实现某个条件。

2、有用过with statement吗?它的好处是什么?

with语句的作用是通过某种方式简化异常处理,它是所谓的上下文管理器的一种

用法举例如下:

 with open('output.txt', 'w') as f:
        f.write('Hi there!')

当你要成对执行两个相关的操作的时候,这样就很方便,以上便是经典例子,with语句会在嵌套的代码执行之后,自动关闭文件。

这种做法的还有另一个优势就是,无论嵌套的代码是以何种方式结束的,它都关闭文件。

如果在嵌套的代码中发生异常,它能够在外部exception handler catch异常前关闭文件。

如果嵌套代码有return/continue/break语句,它同样能够关闭文件。

3、简述 Python 在异常处理中,else 和 finally 的作用分别是什么?

如果一个 Try - exception 中,没有发生异常,即 exception 没有执行,那么将会执行 else 语句的内容。反之,如果触发了 Try - exception(异常在 exception 中被定义),那么将会执行exception
中的内容,而不执行 else 中的内容。

如果 try 中的异常没有在 exception 中被指出,那么系统将会抛出 Traceback(默认错误代码),并且终止程序,接下来的所有代码都不会被执行,但如果有 Finally 关键字,则会在程序抛出 Traceback 之前(程序最后一口气的时候),执行 finally 中的语句。这个方法在某些必须要结束的操作中颇为有用,如释放文件句柄,或释放内存空间等。

4、map 函数和 reduce 函数?

(1) 从参数方面来讲:

map()包含两个参数,第一个参数是一个函数,第二个是序列(列表 或元组)。其中,函数(即 map 的第一个参数位置的函数)可以接收一个或多个参数。

reduce()第一个参数是函数,第二个是序列(列表或元组)。但是,其函数必须接收两个参数。

(2) 从对传进去的数值作用来讲:

map()是将传入的函数依次作用到序列的每个元素,每个元素都是独自被函数“作用”一次 。

reduce()是将传人的函数作用在序列的第一个元素得到结果后,把这个结果继续与下一个元素作用(累积计算)。

补充 Python 特殊函数

lambda 函数

lambda 是一个可以只用一行就能解决问题的函数,让我们先看下面的例子:

>>> def add(x):
...     x += 1
...     return x
...
>>> numbers = range(5)
>>> list(numbers)
[0, 1, 2, 3, 4]
>>> new_numbers = []
>>> for i in numbers:
...     new_numbers.append(add(i))
...
>>> new_numbers
[1, 2, 3, 4, 5]

在上面的这个例子中,函数 add() 充当了一个中间角色,当然上面的例子也可以如下实现:

>>> new_numbers = [i+1 for i in numbers]
>>> new_numbers
[1, 2, 3, 4, 5]

首先我要说,上面的列表解析式其实是很好用的,但是我偏偏要用 lambda 这个函数代替 add(x) :

>>> lamb = lambda x: x+1
>>> new_numbers = []
>>> for i in numbers:
...     new_numbers.append(lamb(i))
...
>>> new_numbers
[1, 2, 3, 4, 5]

在这里的 lamb 就相当于 add(x) ,lamb = lambda x : x+1 就相当于 add(x) 里的代码块。下面再写几个应用 lambda 的小例子:

>>> lamb = lambda x,y : x + y
>>> lamb(1,2)
3
>>> lamb1 = lambda x : x ** 2
>>> lamb1(5)
25

由上面的例子我们可以总结一下 lambda 函数的具体使用方法:lambda 后面直接跟变量,变脸后面是冒号,冒号后面是表达式,表达式的计算结果就是本函数的返回值。

在这里有一点需要提醒的是,虽然 lambda 函数可以接收任意多的参数并且返回单个表达式的值,但是 lambda 函数不能包含命令且包含的表达式不能超过一个。如果你需要更多复杂的东西,你应该去定义一个函数。

lambda 作为一个只有一行的函数,在你具体的编程实践中可以选择使用,虽然在性能上没什么提升,但是看着舒服呀。

map 函数

我们在上面讲 lambda 的时候用的例子,其实 map 也可以实现,请看下面的操作:

>>> numbers = [0,1,2,3,4]
>>> map(add,numbers)
[1, 2, 3, 4, 5]
>>> map(lambda x: x + 1,numbers)
[1, 2, 3, 4, 5]

map 是 Python 的一个内置函数,它的基本格式是:map(func, seq)。

func 是一个函数对象,seq 是一个序列对象,在执行的时候,seq 中的每个元素按照从左到右的顺序依次被取出来,塞到 func 函数里面,并将 func 的返回值依次存到一个列表里。

对于 map 要主要理解以下几个点就好了:

1.对可迭代的对象中的每一个元素,依次使用 fun 的方法(其实本质上就是一个 for 循环)。

2.将所有的结果返回一个 map 对象,这个对象是个迭代器。

我们接下来做一个简单的小题目:将两个列表中的对应项加起来,把结果返回在一个列表里,我们用 map 来做,如果你做完了,请往下看:

>>> list1 = [1,2,3,4]
>>> list2 = [5,6,7,8]
>>> list(map(lambda x,y: x + y,list1,list2))
[6, 8, 10, 12]

你看上面,是不是很简单?其实这个还看不出 map 的方便来,因为用 for 同样也不麻烦,要是你有这样的想法的话,那么请看下面:

>>> list1 = [1,2,3,4]
>>> list2 = [5,6,7,8]
>>> list3 = [9,10,11,12]
>>> list(map(lambda x,y,z : x + y + z,list1,list2,list3))
[15, 18, 21, 24]

你看三个呢?是不是用 for 的话就稍显麻烦了?那么我们在想如果是 四个,五个乃至更多呢?这就显示出 map 的简洁优雅了,并且 map 还不和 lambda 一样对性能没有什么提高,map 在性能上的优势也是杠杠的。

filter 函数

filter 翻译过来的意思是 “过滤器”,在 Python 中,它也确实是起到的是过滤器的作用。这个解释起来略微麻烦,还是直接上代码的好,在代码中体会用法是我在所有的文章里一直在体现的:

>>> numbers = range(-4,4)
>>> list(filter(lambda x: x > 0,numbers))
[1, 2, 3]

上面的例子其实和下面的代码是等价的:

>>> [x for x in numbers if x > 0]
[1, 2, 3]

然后我们再来写一个例子体会一下:

>>> list(filter(lambda x: x != 'o','Rocky0429'))
['R', 'c', 'k', 'y', '0', '4', '2', '9']

reduce 函数

我在之前的文章中很多次都说过,我的代码都是用 Python3 版本的。在 Python3 中,reduce 函数被放到 functools 模块里,在 Python2 中还是在全局命名空间。

同样我先用一个例子来跑一下,我们来看看怎么用:

>>> reduce(lambda x,y: x+y,[1,2,3,4])
10

reduce 函数的第一个参数是一个函数,第二个参数是序列类型的对象,将函数按照从左到右的顺序作用在序列上。如果你还不理解的话,我们下面可以对比一下它和 map 的区别:

>>> list1 = [1,2,3,4]
>>> list2 = [5,6,7,8]
>>> list(map(lambda x,y: x + y,list1,list2))
[6, 8, 10, 12]

对比上面的两个例子,就知道两者的区别,map 相当于是上下运算的,而 reduce 是从左到右逐个元素进行运算。

5、递归函数停止的条件?

递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据判断的结果选择是继续调用自身,还是 return;返回终止递归。

终止的条件:

(1) 判断递归的次数是否达到某一限定值

(2) 判断运算的结果是否达到某个范围等,根据设计的目的来选择

6、回调函数,如何通信的?

回调函数是把函数的指针(地址)作为参数传递给另一个函数,将整个函数当作一个对象,赋值给调用的函数。

7、 __setattr__,__getattr__,__delattr__函数使用详解?

1.setattr(self,name,value):如果想要给 name 赋值的话,就需要调用这个方法。

2.getattr(self,name):如果 name 被访问且它又不存在,那么这个方法将被调用。

3.delattr(self,name):如果要删除 name 的话,这个方法就要被调用了。

下面我们用例子来演示一下:

>>> class Sample:
...    def __getattr__(self,name):
...            print('hello getattr')
...    def __setattr__(self,name,value):
...            print('hello setattr')
...            self.__dict__[name] = value
...

上面的例子中类 Sample 只有两个方法,下面让我们实例化一下:

>>> s = Sample()
>>> s.x
hello getattr

s.x 这个实例属性本来是不存在的,但是由于类中有了 getattr(self,name) 方法,当发现属性 x 不存在于对象的 dict 中时,就调用了 getattr,也就是所谓的「拦截成员」。

>>> s.x = 7
hello setattr

同理,给对象的属性赋值的时候,调用了 setattr(self,name,value) 方法,这个方法中有 self.dict[name] = value,通过这个就将属性和数据存到了对象 dict 中。如果再调用这个属性的话,会成为下面这样:

>>> s.x
7

出现这种结果的原因是它已经存在于对象的 dict 中了。

看了上面的两个,你是不是觉得上面的方法很有魔力呢?这就是「黑魔法」,但是它具体有什么应用呢?我们接着来看:

class Rectangle:
   """
   the width and length of Rectangle
   """

   def __init__(self):
       self.width = 0
       self.length = 0

   def setSize(self,size):
       self.width, self.length = size

   def getSize(self):
       return self.width, self.length

if __name__ == "__main__":
   r = Rectangle()
   r.width = 3
   r.length = 4
   print(r.getSize())
   print(r.setSize((30,40)))
   print(r.width)
   print(r.length)

上面是我根据一个很有名的例子改编的,你可以先想一下结果,想完以后可以接着往下看:

(3, 4)
30
40

这段代码运行的结果如上面所示,作为一个强迫证的码农,对于这种可以改进的程序当然不能容忍。我们在上面介绍的特殊方法,我们一定要学以致用,虽然重新写的不一定比原来的好,但我们还是要尝试去用:

class NewRectangle:
   """
   the width and length of Rectangle
   """

   def __init__(self):
       self.width = 0
       self.length = 0

   def __setattr__(self, name, value):
       if name == 'size':
           self.width, self.length = value
       else:
           self.__dict__[name] = value

   def __getattr__(self, name):
       if name == 'size':
           return self.width, self.length
       else:
           return AttributeError

if __name__ == "__main__":
   r = NewRectangle()
   r.width = 3
   r.length = 4
   print(r.size)
   r.size = 30,40
   print(r.width)
   print(r.length)

我们来看一下运行的结果:

(3, 4)
30
40

我们可以看到,除了类的写法变了以外,调用的方式没有变,结果也没有变。

8、请描述抽象类和接口类的区别和联系?

(1) 抽象类

规定了一系列的方法,并规定了必须由继承类实现的方法。由于有抽象方法的存在,所以抽象类不能实例化。可以将抽象类理解为毛坯房,门窗、墙面的样式由你自己来定,所以抽象类与作为基类的普通类的区别在于约束性更强。

(2) 接口类

与抽象类很相似,表现在接口中定义的方法,必须由引用类实现,但他与抽象类的根本区别在于用途:与不同个体间沟通的规则(方法),你要进宿舍需要有钥匙,这个钥匙就是你与宿舍的接口,你的同室也有这个接口,所以他也能进入宿舍,你用手机通话,那么手机就是你与他人交流的接口。

(3) 区别和关联

  • 接口是抽象类的变体,接口中所有的方法都是抽象的。而抽象类中可以有非抽象方法。抽象类是声明方法的存在而不去实现它的类。

  • 接口可以继承,抽象类不行。

  • 接口定义方法,没有实现的代码,而抽象类可以实现部分方法。

  • 接口中基本数据类型为 static 而抽类象不是。

  • 接口可以继承,抽象类不行。

  • 可以在一个类中同时实现多个接口。

  • 接口的使用方式通过 implements 关键字进行,抽象类则是通过继承 extends 关键字进行。

9、请描述方法重载与方法重写?

(1)方法重载

是在一个类里面,方法名字相同,而参数不同。返回类型呢?可以相同也可以不同。重载是让类以统一的方式处理不同类型数据的一种手段。

(2) 方法重写

子类不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。

10、什么是 lambda 函数? 有什么好处?

lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数

1、lambda 函数比较轻便,即用即仍,很适合需要完成一项功能,但是此功能只在此一处使用,连名字都很随意的情况下

2、匿名函数,一般用来给 filter, map 这样的函数式编程服务

3、作为回调函数,传递给某些应用,比如消息处理


以上就是今天的内容,我是帅蛋,我们明天见~

❤️ 欢迎关注我,有问题,找帅蛋,我最看不得别人迷茫!

❤️ 如果你觉得有帮助,希望爱学习的你不要吝啬三连击哟[点赞 + 收藏 + 评论]~

还有小小公众号 【编程文青李狗蛋】,聊聊迷茫吹吹牛皮~

#帅蛋的面试空间##秋招##面试八股文##Python##python面试#
全部评论
来啦来啦,Python 进阶题第二弹他来啦!
1 回复
分享
发布于 2022-07-25 14:34
每天都跟着大佬学,每天进步一点点,不积跬步,无以至千里!
点赞 回复
分享
发布于 2022-07-25 15:01
联想
校招火热招聘中
官网直投
有问题,找帅蛋!
点赞 回复
分享
发布于 2022-07-25 20:45
厉害
点赞 回复
分享
发布于 2022-07-26 10:58
麻溜跑来学习😁
点赞 回复
分享
发布于 2022-07-26 19:47
果断收藏了,希望面试用得到
点赞 回复
分享
发布于 2022-07-26 20:09
每天都在努力进步,感谢楼主的分享
点赞 回复
分享
发布于 2022-07-26 20:55
支持,跟着学习
点赞 回复
分享
发布于 2022-07-27 00:34
跟着学Python
点赞 回复
分享
发布于 2022-07-27 22:34
Python校招岗位好像不太多啊
点赞 回复
分享
发布于 2022-08-31 02:08 北京

相关推荐

34 136 评论
分享
牛客网
牛客企业服务