Python 八股

解释型语言和编译型语言

编译型语言

通过专门的编译器,把所有源代码一次转换为特定平台的可执行文件,然后再运行。一次编译,多次执行。比如C,C++。

优点 :

  • 一次编译,多次运行。
  • 脱离编译环境,并且运行效率高

缺点:

  • 依靠编译器跨平台性差可移植性差编译的时候根据对应的运行环境生成机器码,不同的操作系统之间移植就会有问题,需要根据运行的操作系统环境编译不同的可执行文件。
  • 编译之后如果需要修改就需要整个模块重新编译

解释型语言

由专门的解释器,根据需要将部分源代码临时转换成特定平台的机器码,然后执行。边解释边执行。比如Python, PHP.

优点:

  • 跨平台性好,通过不同的解释器,将相同的源代码解释成不同平台下的机器码。

缺点:

  • 一边执行一边转换,效率不高

混合型语言

如Java, C#。兼具执行效率和跨平台性,不直接编译成机器码,需要先编译成中间码(java是编译成字节码),需要中间语言运行库类似java虚拟机(JVM),边解释边运

is和==的区别

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

os和sys的区别

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

sys模块负责程序与Python解释器的交互。

可变对象和不可变对象

在python中,一切皆对象,对象必有的三个属性:地址、类型、值

可变对象

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

不可变对象

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

注意:如果直接将list2 = list1,那么list1和list2的地址会是相同的。只是换了不同的名称而已。

深拷贝和浅拷贝

  • 浅拷贝,指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用

list1 = [1, 2, 3] list2 = list(list1)

list3 = list1[:] print("list1==list2 ?",list1==list2) True print("list1 is list2 ?",list1 is list2) False 浅拷贝

print("list1 is list3 ?",list1 is list3) False 浅拷贝

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

import copy list1 = [[1, 2], (30, 40)] list2 = copy.deepcopy(list1)

*arg 和 **kwarg 作用

允许我们在调用函数的时候传入多个实参

*arg 会把位置参数转化为 tuple**kwarg 会把关键字参数转化为 dict

with如何使用

with所求值的对象必须有一个enter()方法,一个exit()方法。

with**后面的语句被求值后,返回对象的**__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的exit()方法。

with open("/tmp/foo.txt") as file:

data = file.read()

__new__和__init__

__init__为初始化方法,__new__方法是真正的构造函数。 __new__是实例创建时被调用,它的任务是创建并返回该实例,是静态方法 __init__是实例创建之后被调用的,然后设置对象属性的一些初始值

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

装饰器

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

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

Python的装饰器广泛应用于缓存权限校验(如django中的@login_required和@permission_required装饰器)、性能测试比如统计一段程序的运行时间)和插入日志等应用场景。

示例代码:

from decorator import decorator

@decorator

def hint(func, *args, **kwargs):

print('{} is running'.format(func.__name__))

return func(*args, **kwargs)

迭代器和生成器

可迭代对象

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

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

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

迭代器

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

>>> list=[1,2,3,4]

>>> it = iter(list) # 创建迭代器对象

>>> print (next(it))

>>> print (next(it))

生成器

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

def func2(): print('######') yield 100 print('------') yield 200 print('======') return 300

fliter map reduce

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

>>> mylist = list(range(10))

>>> list(filter(lambda x: x % 2 == 1, mylist))

[1, 3, 5, 7, 9]

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

    >>> list(map(lambda x: x % 2, mylist)) [1, 0, 1, 0, 1, 0, 1, 0, 1]

      reduce 函数用于递归计算,同样需要传入一个函数和一个序列,并把函数和序列元素的计算结果与下一个元素进行计算

      >>> from functools import reduce

      >>> reduce(lambda x, y: x + y, range(101))

      5050

全局变量 局部变量 闭包

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

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

作用:

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

闭包经典问题:

[lambda x: x*i for i in range(4)]

res = [m(2) for m in lst] print(res)

  • 预计结果为:[0, 2, 4, 6]
  • 实际输出为:[6, 6, 6, 6]

[lambda x: x*i for i in range(4)] --> [lambda x, i = i: x*i for i in range(4)]

等价于

def func():

fun_list = []

for i in range(4):

def foo(x):

return x*i

fun_list.append(foo)

return fun_list //是一个链表【foo(x), foo(x), foo(x), foo(x)】

i在外层作用域lambda x: x*i 为内层(嵌)函数,他的命名空间中只有 {'x': 1} 没有i,所以运行时会向外层函数(这里是列表解析式函数[])的命名空间中请求i,而当列表解析式运行时,列表解析式命名空间中的i经过循环依次变化为0-->1-->2-->3最后固定为3,所以当 lambda x: x*i内层函数运行时,去外层函数取i每次都只能取到 3。

变闭包作用域为局部作用域, foo()中添加i=i

def func():

fun_list = []

for i in range(4):

def foo(x, i=i):

return x * i

fun_list.append(foo)

return fun_list

for m in func():

  print(m(2))

匿名函数

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

lambda表达式的意义两点:

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

垃圾回收机制

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

1.引用计数

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

优点:

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

缺点:

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

2.标记清除

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

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

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

3.分代回收

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

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

参考链接:

解释型语言

https://blog.csdn.net/jackcong_/article/details/116173078

https://www.cnblogs.com/superwuchaofan/p/16550375.html

全局变量

https://blog.csdn.net/weixin_45043349/article/details/120494883

八股

https://blog.csdn.net/qq_37621623/article/details/123353485

垃圾回收

https://blog.csdn.net/qq_37085158/article/details/126213782

https://wenku.baidu.com/view/e2b43fd4fa0f76c66137ee06eff9aef8941e48d9.html?_wkts_=1669344734124

闭包

https://blog.csdn.net/qq_37085158/article/details/124734978

装饰器

https://blog.csdn.net/qq_37085158/article/details/124933649

os和sys

https://www.jianshu.com/p/31cee25fc428

可变对象和不可变对象

https://www.jb51.net/article/223840.htm

浅拷贝和深拷贝

https://blog.csdn.net/qq_40630902/article/details/119278072

with的用法

https://blog.csdn.net/qq_35985044/article/details/125408938

迭代器和生成器

https://blog.csdn.net/qq_54259749/article/details/125685621

https://www.runoob.com/python3/python3-iterator-generator.html

python八股

https://blog.csdn.net/qq_37085158/article/details/126821933

全部评论
sys 主要是 python解释器和系统环境之间的交互,例如处理输入输出之类的,例如sys.version
点赞 回复 分享
发布于 2025-04-13 15:29 湖南
大佬666,总结的很好,受教了
点赞 回复 分享
发布于 2022-12-20 14:30 新加坡

相关推荐

2025-11-21 22:25
门头沟学院 HTML5
我是个没天赋的人,努力学习也只考上了个一本,家里条件也不怎么样。大一玩了一年,没怎么学技术,也没有卷绩点,全在游戏小说抖音中度过。大二上接触了牛客,看到了许多优秀的同龄人。很多双非的同学,甚至不少学院本的同学都进了大厂实习。我把他们作为榜样,决定好好学习。我每天都至少学八九个小时,很多次都想要放弃,想哭,我都坚持了下来。我总是告诉自己,只要努力,就一定能有好的结果。这几个月过的很累,但也很充实。转眼就到大二下了,我决定去找实习了,但是学校的认可度让我感到心底发凉,明明和广工这种知名双非分差不多,结果总被问是不是公办本科。两个月投了一千份实习,只有四个面试,最终去了个中小厂实习。结果就是改了两个月bug,虽然mt人挺好,但是实在学不了什么东西,所以就离职开始面试。凭借这段实习,确实多了不少中小厂面试,但是大厂依旧没有面试机会。除了字节腾讯所有大厂都投了,结果依旧是0面试。最终有幸获得美团的面试机会,面试也幸运的通过,然后入职了。为了省钱坐十几个小时硬座到北京,到北京的第一天,由于太激动想要租房,结果被坑了2600,之前实习的地方,房东也故意不退押金,加起来总共损失3000多。虽然很难过,但是我还是忍受了下来,我想着实习才刚开始,会好起来的。实习了大半个月,跟学校这边沟通一直不成功,我每天都寝食难安,精神都快崩溃了,经常凌晨两三点才睡着,想要跳楼。最后迫于无奈,我一大早我坐高铁回去,恳求院主任给我一个机会,我怎么恳求讲理都没用,甚至都磕头下跪了,还是没用。院主任一点机会都没给我,连让我跟各科老师沟通机会都不给,要不休学要不辞职。我没得选择,这段实习我看的比我的生命还重要,这不仅是我这大半年的心血,更是未来的一份希望。我只能休学,我想着现在好好实习,多学点技术,到时候秋招早点拿到offer,然后再补这学期的课也不是不行。但是,现实总是事与愿违。这三个月说实话并没有学到什么东西,前一个月很闲,这两个月事很多,每天基本都是九点后下班,但都是杂活。产出都是靠我看文档加上代码写上去的。我真的很想锻炼一下技术,但是总是不尽人意。三个月了,我到现在都还没做过一个像样点的需求。产出是能编,但有破绽不说还没锻炼到技术。我好想真正的做一下需求啊,我好想真正的走完一遍流程,去上线一次啊。接下来两个月,我不知道该怎么坚持下去了,现在每天都想哭,很焦虑,很难受。冒着将来可能延毕的风险,我赌上了一切,结果输的这么彻底,可能我就只是个小丑吧。如果家庭好点就不用卷了,如果我聪明一点就能上个好学校了,如果大一有人带我,我就不会摆烂了,如果院主任给我个机会,我就不用这么苦了,如果我实习能有机会好好锻炼自己,我就不用这么难受焦虑了。但是没办法,我又能怎么办呢,无非是咬紧牙关罢了,毕竟没人能够帮助我,只能靠自己我可真是个小丑啊
HasonoCell:你很棒了bro....其实我看网上休学一年的人很多的也都顺利毕业了,真的不用特别焦虑这个事。另外实习也是,有一段大厂实习已经比很多很多人厉害了,跟你一届的很多人现在估计都没意识到未来的压力呢,实习就算没产出也不用特别焦虑,好好总结一下已经做过的事情,然后趁着休学这年继续冲一下,要相信未来会有好结果的。你应该也挺眼熟我的,我之前字节横向挂的时候也是难过的不行,觉得自己好没用,结果百度出乎意料的offer了,很多事其实都很顺其自然,认真做事,好结果也许就在下个路口等着你。 很喜欢的一句话是:木已成舟。不要老是沉浸在过去的遗憾中无法自拔噢,要努力过好当下。 好好休息一下吧,辛苦了,你已经很棒了噢
点赞 评论 收藏
分享
评论
43
277
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务