Python 基础面经(整理)

整理看到或者查到的面试题以及答案

目录

1 什么是Python?

2  is和 == 的区别?

3 os和sys的区别?

4 可变对象和不可变对象?

5 赋值、浅拷贝和深拷贝的区别?

6 *args 和 **kwargs作用?

7  __new__ 和 __init__的区别?

8 什么是装饰器?

9 什么是迭代器和生成器?

10 filter 、map 和 reduce是什么?

11 什么是全局变量、局部变量?

12 什么是闭包?

13 什么是匿名函数?

14 python中类方法、类实例方法、静态方法有何区别?

15 什么是垃圾回收机制?


1 什么是Python?

Python是一种编程语言,它有对象、模块、线程、异常处理和自动内存管理,相对于其他语言python具有良好的跨平台性且容易学习,同时python是解释型语言,在代码运行前不需要解释,代码修改简单方便。但是python的执行速度不够快。

2  is和 == 的区别?

== 是比较字符,只是判断对象的是否一致,而is则判断的是对象的身份(内存地址)是否一致。对象的身份可以通过id()方法来查看。

3 os和sys的区别?

os模块是Python标准库中提供的与操作系统交互的模块,提供了访问操作系统底层的接口,里面有很多操作系统的接口。

sys模块负责与python解释器的交互

4 可变对象和不可变对象?

在python中,一切对象都包含三个属性:地址、类型、值

可变对象:

  • 当对象的值发生变化,但内存地址没有发生变化时,则说明是可变对象
  • 可变对象:列表、字典、集合。
  • 引用可变对象时,会创建新的内存地址,当可变对象的值发生变化时,原内存地址不会改变
  • 引用传递:主函数向调用函数传递的参数是可变类型时,实际上是将实参的引用传入了调用函数,对引用的操作等于对其指定的对象进行操作。

不可变对象:

  • 当对象的值发生变化时,但内存地址也发生改变时,则说明是不可变类型
  • 不可变对象:元组、字符串、数值
  • 在引用不可变对象时,会寻找该对象是否被创建过,若该对象已经创建,则变量会直接引用该对象,不会在申请新的内存空间。
  • 值传递:主函数向调用函数传递的参数是不可变的类型时,实际上只是将实参的拷贝(即临时副本)传递给了被调用函数,并不是实参本身,这样被调函数不能直接修改主函数中变量的值。

5 赋值、浅拷贝和深拷贝的区别?

赋值:

在python中,对象的赋值就是简单的对象调用

a = [1 , 2, "hello", ["python", "C++"]
b = a

在上述的情况下,a和b是一样的,它们指向同一片内存,b只不过是a的别名,是引用。

赋值操作(包括对象作为参数、返回值)不会开辟新的空间,他只是复制了对象的引用。也就是说除了b这个名字外,没有其他内存的开销。修改了a,也就是影响了b,同理,修改了b也就影响了a。

浅拷贝:

浅拷贝是指重新分配一个内存空间,创建一个新的对象,但里面的元素是原对象中第一层对象的引用

浅拷贝有操作:切片操作、工厂函数、copy.copy()函数。

b = a[:]  or b = [i for i in a]  # 切片操作
b = list(a)   # 工厂函数
b = copy.copy(a) #copy函数

浅拷贝后列表a和b是不同的对象,修改列表b理论上不会影响到列表a。但是要注意的是,浅拷贝值拷贝了一层,在列表a中有一个嵌套的list,如果我们修改了它,情况就不一样了。

深拷贝:

深拷贝是指重新分配一块内存,创建一个新的对象,并对原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联

6 *args 和 **kwargs作用?

允许调用函数时,传入多个实参

*args 会把位置参数转化为tuple(元组)

*kwargs 会把关键字参数转化为 dict(字典)

7  __new__ 和 __init__的区别?

__new__方法是真正的构造函数,是实例创建时被调用,它的任务是创建并返回该实例,是静态方法

__init__方法是初始化方法,是实例创建之后被调用的,然后设置对象属性的一些初始值

__new__方法在__init__方法之前被调用,并且__new__方法的返回值将传递给__init__方法作为第一个参数,最后__init__给这个实例设置一些参数。

8 什么是装饰器?

参考使用:

(3条消息) python装饰器这一篇就够了_凸头拯救地球的博客-CSDN博客_python装饰器

Python的装饰器本质上是一个嵌套函数,它接受被装饰的函数(func)作为参数,并返回一个包装过的函数

作用:在不修改被装饰对象源代码以及调用方式的前提下为被装饰对象添加新功能

装饰器模板:

import functools


def outer(origin):
    @functools.wraps(origin)
    def inner(*args, **kwargs):
        # 这里写需要的功能
        res = origin(*args, **kwargs):
        return res
    
    return inner

9 什么是迭代器和生成器?

可迭代对象:

python中一个非常强大的功能,它可以访问容器(字符串、列表、元组、集合、字典、range

迭代是通过for循环遍历对象中的每一个元素,将元素取出来的过程,所以:容器都是可迭代的对象

可迭代对象除了包含常见的序列,还包括一个叫迭代器的东西

迭代器:

  • 迭代器是一个可以记住遍历的位置的对象
  • 迭代器对象从集合的第一个元素开始访问,直到所有元素被访问完结束。迭代器只能往前不会后退
  • 迭代器有两个基本方法:iter() next()
  • 字符串、列表或元组对象都可以用于创建迭代器。

生成器:

  • 在python中,使用了yield的函数被称为生成器
  • 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作
  • 在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息返回yield的值,并在下一次执行next()方法时从当前位置继续运行
  • 调用生成器函数时,函数体并不执行,只返回一个生成器对象
  • 在对生成器对象使用next方法或者遍历的时候,生成器函数体才真正执行

参考博客:

(3条消息) python中yield的用法详解——最简单,最清晰的解释_冯爽朗的博客-CSDN博客_python yield

10 filter 、map 和 reduce是什么?

filter函数:用于过滤序列,它接收一个函数和一个序列,把函数作用在序列的每个元素上,然后根据返回值是True还是False决定保留还是丢弃该元素

mylist = list(range(10))
print(list(filter(lambda x: x % 2 == 1, mylist)))


[1, 3, 5, 7, 9]

map函数:传入一个函数和一个序列,并把函数作用到序列的每一个元素上,返回一个可迭代对象。

print(list(map(lambda x: x % 2, mylist)))

[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

reduce函数: 用于递归计算(列表累加求和),需要传入一个函数和一个序列,并把函数和序列元素的计算结果与下一个元素进行计算

from functools import reduce
print(reduce(lambda x, y: x + y, range(101))

5050

11 什么是全局变量、局部变量?

函数外声明的变量是全局变量。只在函数内起作用的变量叫做局部变量。全局变量可以在函数中直接进行访问,但是在修改全局变量时,为了避免与局部变量产生混淆,需要先加上global声明,然后在修改。

12 什么是闭包?

闭包:闭包是python编程一个非常重要的概念。如果一个外函数中定义了一个内涵数,且内函数引用到了体外的变量,这时外函数通过return 返回内函数的引用时,会把定义时涉及到的外部引用变量和内函数打包成一个整体(闭包)返回。

作用:即使外函数已经结束了,内函数依然能够使用外函数的临时变量。

闭包实际上就是一个函数,但是这个函数要具有:

  1. 定义在另外一个函数里面(嵌套函数);
  2. 引用其所在环境的自由变量。
def fun(a, b, c):
    def para(x):
        return a * x ** 2 + b * x + c
    return para

f = fun(1, 2, 3)
print(f(2))

11

上面的函数中,f=fun(1,2,3)定义了一个一元二次函数的函数对象,如果要计算x= 2,只需要计算f(2)即可。

13 什么是匿名函数?

匿名函数的关键字是lambda,表现形式:lambda 参数:返回值,lambda后面的参数就是函数的形参,冒号后面的表达式就是返回值。

lambda表达式的意义两点:

  1. 对于只有一行的函数,使用此方式可以省去定义函数的过程,使代码简洁明朗
  2. 对于不需要重复使用之函数,此方式可以用完之后,立即释放,提高程序执行的性能。

虽然lambda函数可以接收任意多个的参数并返回当个表达式的值,但是lambda函数不能包含命令且包含的表达式不能超过一个。

14 python中类方法、类实例方法、静态方法有何区别?

参考:

Python实例方法、静态方法和类方法详解(包含区别和用法)

类方法:是类对象的方法,在定义的时候需要在上方使用"@classmethod"进行装饰,形参为cls,表示类对象,类对象和实例对象都可调用。

类实例方法:是类实例化对象的方法,只有实例对象可以调用,形参为self,指代对象本身。

静态方法:是一个任意函数,在其上方使用"@staticmethod"进行装饰,可以用对象直接调用,静态方法实际上跟该类没有太大关系。

15 什么是垃圾回收机制?

引用计数(主要手段)+标记清除(辅助)+分代回收(辅助)

1.引用计数

在Python中,使用了引用计数这一技术实现内存管理。一个对象被创建完成后就有一个变量指向这个对象,那么就这个对象的引用计数为1,以后如果有其他变量指向这个对象,其引用计数也会相应增加,如果将一个变量不再执行这个对象,那么这个对象的引用计数减1。如果一个对象没有任何变量指向这个对象,也即引用计数为0,那么这个对象会被Python回收。

优点:

  • 高效。
  • 运行期没有停顿。可以类比一下Ruby的垃圾回收机制,也就是实时性:一旦没有引用,内存就直接释放了。不用像其他机制等到特定时机。实时性还带来一个好处:处理回收内存的时间分摊到了平时。
  • 对象有确定的生命周期。
  • 易于实现。

缺点:

  • 维护引用计数消耗资源,维护引用计数的次数和引用赋值成正比。
  • 无法解决循环引用的问题。比如现在有两个对象分别为aba指向了bb又指向了a,那么他们两的引用计数永远都不会为0。也即永远得不到回收。

2.标记清除

针对循环引用的情况,Python引入标记清除算法。

标记清除算法是一种基于追踪回收技术实现的垃圾回收算法。它分为两个阶段:

  • 第一阶段是标记阶段,GC会把所有的活动对象打上标记
  • 第二阶段是把那些没有标记的对象非活动对象进行回收。

3.分代回收

分代回收是建立在标记清除技术基础之上的,是一种以空间换时间的操作方式。

Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一“代”, Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾回收机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。

举个例子:
当某些内存块 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 的默认内存管理行为。

参考:

牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决_牛客网 (nowcoder.com)

  • 3
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python基础知识整理包括以下几个方面: 1. 数据类型:Python中常见的数据类型有整数(int)、浮点数(float)、字符串(str)、布尔值(bool)、列表(list)、元组(tuple)、字典(dict)等。 2. 变量和赋值:在Python中,可以使用变量来保存数据,并使用赋值语句将值赋给变量。变量名可以由字母、数字和下划线组成,但不能以数字开头。 3. 运算符:Python支持常见的算术运算符(如加减乘除)、比较运算符(如等于、大于、小于等)、逻辑运算符(如与、或、非)等。 4. 控制流程:Python中的控制流程包括条件语句(if-else)、循环语句(while和for)以及跳转语句(break和continue)等。 5. 函数和模块:函数是一段可重复使用的代码块,可以通过函数来组织代码和实现代码的复用。而模块是一个包含了函数、类和变量的文件,可以通过import语句导入并使用。 6. 异常处理:在编写程序时,可能会出现错误,为了避免程序崩溃,可以使用异常处理机制来捕捉和处理错误,保证程序的正常执行。 7. 文件操作:Python提供了丰富的文件操作函数,可以读取和写入文件内容,以及对文件进行其他操作。 8. 面向对象编程:Python是一种面向对象的编程语言,支持类和对象的概念,可以通过定义类来创建对象,并使用对象调用类中的方法和属性。 这些是Python基础知识的主要内容,希望对你有所帮助。如果你有具体的问题,可以继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值