python近期遇到的一些面试问题(二)

1. 解释什么是栈溢出,在什么情况下可能出现。

栈溢出是由于C语言系列没有内置检查机制来确保复制到缓冲区的数据不得大于缓冲区的大小,因此当这个数据足够大的时候,将会溢出缓冲区的范围。
在Python中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
以上内容来自百度百科。https://baike.baidu.com/item/%E6%A0%88%E6%BA%A2%E5%87%BA/8538051?fr=aladdin

栈溢出的几种情况:

  1. 局部数组过大,当函数内部的数组过大时,有可能导致堆栈溢出。
  2. 递归调用层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致堆栈溢出。
  3. 指针或数组越界。这种情况最常见,例如进行字符串拷贝,或处理用户输入等等。
    以上内容来自,https://blog.csdn.net/u010590166/article/details/22294291/

2.简述Cpython的内存管理机制

Python和其他高级编程语言,如Java、Ruby或JavaScript等一样,有自动内存管理机制。所以许多程序开发人员没有过多地关注内存管理,但是这可能会导致更多的内存开销和内存泄漏。这篇文章是关于CPython(Python解释器)是如何管理对象的生命周期的深度剖析,文章是我在GitHub上的 vprof 工程中记录来的,希望对大家有帮助。

引用计数

每一个Python对象都有一个引用计数器----用于记录有多少其他对象指向(引用)这个对象。它存储在变量 refcnt 中,并通过调用C宏Py_INCREF实现引用计数增加和Py_DECREF实现引用计数减少的操作。 Py_DECREF更复杂点,当引用计数器到零时,它会运行该对象的释放函数,回收该类型的对象。

通常以下两种情况你需要考虑这个宏定义:实现自己创建数据结构,或者修改已经存在的Python C API。如果你使用Python内置的数据结构,那么不需要任何操作。

如果想不增加引用计数,可以使用弱引用或 weakrefs 引用对象。 Weakrefs对于实现缓存和代理非常有用。

垃圾回收(GC)

引用计数是在Python 2.0之前管理对象生命周期的唯一方法。它有一个弱点,它不能删除循环引用的对象。 循环引用的最简单的例子是对象引用自身。


通常情况下,可以避免使用循环引用对象,但是有时是不可避免的(例如:长时间运行的程序)。

为了解决这个问题,Python 2.0引入了新的垃圾回收机制。 新GC与其他语言运行时(如JVM和CLR)的GC的主要区别在于,它仅用于寻找存在引用计数的循环引用。

循环引用只能由容器对象创建,因此Python GC不会跟踪整数,字符串等类型。

GC将对象分为3代,每一代对象都有一个计数器和一个阈值。当对象被创建时,阈值会被自动地指派为0,也就是第0代对象。当计数器大于某个阀值,GC就会运行在当前对象代上,回收该对象。没被回收的对象会被移至下一代,并且将相应的计数器复位。下一代的对象保留在下一代。

在Python 3.4之前,GC有一个致命缺点----每个对象重载了del__()方法,因为每个对象都可以相互引用,所以GC不知道该调用那个对象的__del()方法,这会导致GC直接跳过这些对象。具体详细信息可以参考 gc.garbage并且循环引用需要编程人员手动打破。

Python3.4介绍了一种最终的解决方法finalization approach ,现在的GC可以打破对象的循环引用,而不在使用gc.garbage介绍的方法去回收对象。

此外,值得一提的是,如果你确定你的代码没有创建循环引用(或者你不关心内存管理),那么你可以只依赖引用计数器自动管理内存,而不使用GC去管理内存。

以上内容来自:,https://python.freelycode.com/contribution/detail/511
英文原文:https://medium.com/@nvdv/cpython-memory-management-479e6cd86c9#.sbvb0py87

3.请列举你知道的Python的魔法方法及用途。

__init__

构造器,当一个实例被创建的时候调用的初始化方法

__new__

  1. __new__ 是在一个对象实例化的时候所调用的第一个方法
  2. 它的第一个参数是这个类,其他的参数是用来直接传递给 __init__ 方法
  3. __new__ 决定是否要使用该 __init__ 方法,因为 __new__ 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 __new__ 没有返回实例对象,则 __init__ 不会被调用
  4. __new__ 主要是用于继承一个不可变的类型比如一个 tuple 或者 string

__call__

允许一个类的实例像函数一样被调用

__del__

析构器,当一个实例被销毁的时候调用的方法

__len__(self): 定义当被 len() 调用时的行为
__repr__(self): 定义当被 repr() 调用时的行为
__str__(self): 定义当被 str() 调用时的行为
__bytes__(self):定义当被 bytes() 调用时的行为
__hash__(self): 定义当被 hash() 调用时的行为
__bool__(self): 定义当被 bool() 调用时的行为,应该返回 True 或 False

4. 已知以下list:

list1 = [
{
"mm": 2,
},{
"mm": 1,
},{
"mm": 4,
},{
"mm": 3,
},{
"mm": 3,
}
]

4.1 把list1中的元素按mm的值排序。

首先说函数sorted的具体用法:

(1).Python2.x:sorted(iterable, cmp=None, key=None, reverse=False)
,Python3.x:sorted(iterable, /, *, key=None, reverse=False),Python3.x和Python2.x的sorted函数有点不太一样,少了cmp参数。
key接受一个函数,这个函数只接受一个元素,默认为None
reverse是一个布尔值。如果设置为True,列表元素将被倒序排列,默认为False
着重介绍key的作用原理:
key指定一个接收一个参数的函数,这个函数用于从每个元素中提取一个用于比较的关键字。默认值为None 。

(2).sorted() 函数对所有可迭代的对象进行排序操作。
(3).对于 元组类型的列表比如

list2=[(‘b‘,4),(‘a‘,0),(‘c‘,2),(‘d‘,3)]

排序的方法是使用lambda然后获取需要排的元素的下标即可。

print(sorted(list2,key=lambda x:x[0]))

而本题有点麻烦 里面是字典类型所以我们需要通过以下方式获取

答案 :

sorted(list1,key=lambda x:x.items()[0][1])

或者

sorted(list1,key=lambda x:x[‘mm‘]))

或者用 operator 函数来加快速度, 上面排序等价于

from operator import itemgetterprint(sorted(list1,key=itemgetter(‘mm‘)))

4.2 获取list1中第一个mm值等于x的元素。
4.3 删除list1中所有mm等于x的元素,且不对list重新赋值。
4.4 取出list1中mm最大的元素,不能排序。

后续

原文地址:https://www.cnblogs.com/c-x-a/p/9226739.html

时间: 2024-08-01 09:03:07

python近期遇到的一些面试问题(二)的相关文章

python近期遇到的一些面试问题(三)

整理一下最近被问到的一些高频率的面试问题.总结一下方便日后复习巩固用,同时希望可以帮助一些朋友们. 前两期点这↓ python近期遇到的一些面试问题(一) python近期遇到的一些面试问题(二) 1.请写一个邮箱的正则表达式 电子邮件地址有统一的标准格式:用户名@服务器域名.用户名表示邮件信箱.注册名或信件接收者的用户标识,@符号后是你使用的邮件服务器的域名.@可以读成"at",也就是"在"的意思.整个电子邮件地址可理解为网络中某台服务器上的某个用户的地址. 答案

python近期遇到的一些面试问题(一)

整理一下最近被问到的一些高频率的面试问题.总结一下方便日后复习巩固用,同时希望可以帮助一些朋友们. 1.python的基本数据类型 主要核心类型分为两类不可变类型:数字(int float bool complex),字符串(string),元祖(tuple),不可变集合(frozenset). 可变类型:列表(list),字典(dict),集合(set)这里的可变不可变,是指内存中的值是否可以被改变 补充一点,其中不可变集合就是一个无序的不可变的集合,元素也只能是可hash的主要用来做字典的键

用python + hadoop streaming 编写分布式程序(二) -- 在集群上运行与监控

写在前面 前文:用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试 为了方便,这篇文章里的例子均为伪分布式运行,一般来说只要集群配置得当,在伪分布式下能够运行的程序,在真实集群上也不会有什么问题. 为了更好地模拟集群环境,我们可以在mapred-site.xml中增设reducer和mapper的最大数目(默认为2,实际可用数目大约是CPU核数-1). 假设你为Hadoop安装路径添加的环境变量叫$HADOOP_HOME(如果是$HAD

Python 爬虫 之 阅读呼叫转移(二)

上一篇博客我们成功地从网页上爬下了小说的一个章节,理所当然地,接下来我们要把整本小说都爬下来.首先,我们要把程序从原来的读完一章就结束,改成读完一章之后可以继续进行下一章的阅读. 注意到每个小说章节的网页下面都有下一页的链接.通过查看网页源代码,稍微整理一下(  不显示了),我们可以看到这一部分的 HTML 是下面这种格式的: <div id="footlink"> <script type="text/javascript" charset=&q

记一次Python Web后端开发电话面试

电话面试是在前天周三下午就约好了的.原本电话那头是想当时就进行沟通的,但在得知我在上班后选择了另约时间,刚好那天晚上面试官也没时间,遂改为周六9:30~10:00这个时间. 昨天不知是怎么了,可能是在公司盯屏幕盯太久了,一回来发现右眼已经满眼血丝,吃完晚饭后眼睛也是疼得不行,所以8点多就不知不觉睡着了.半夜十二点多醒来,发现睡不着了,玩了会手机又重新调了下闹钟,生怕睡过头了.还好,八点十多分醒过来了,九点左右已经做好接电话的准备了,趁着还有半个小时还赶忙把<Flask Web开发>这本书给过了

python基础学习 第十七天 (二)

python基础学习 第十七天 (二) 一. 魔法方法 定义:双下方法是特殊方法,他是解释器提供的 由爽下划线加方法名加双下划线 方法名的具有特殊意义的方法,双下方法主要是python源码程序员使用的,我们在开发中尽量不要使用双下方法,但是深入研究双下方法,更有益于我们阅读源码. 调用:不同的双下方法有不同的触发方式,就好比盗墓时触发的机关一样,不知不觉就触发了双下方法,例如:init 1.1 len class B: def __len__(self): print(666) b = B()

Python中的多进程与多线程(二)

在上一章中,学习了Python多进程编程的一些基本方法:使用跨平台多进程模块multiprocessing提供的Process.Pool.Queue.Lock.Pipe等类,实现子进程创建.进程池(批量创建子进程并管理子进程数量上限)以及进程间通信.这一章学习下Python下的多线程编程方法. 一.threading 线程是操作系统执行任务的最小单元.Python标准库中提供了threading模块,对多线程编程提供了很便捷的支持. 下面是使用threading实现多线程的代码: 1 #!/us

Python初体验之基础语法(二)

所有测试语句基于Python 2.7.6 , Ubuntu 14.04 LTS 自学Python,如果哪里说的不对,还请指正.谢谢. 示例绝大部分来自博客园vamei的python教程 1.文件读写操作 一. 按字节读取文件 #!/usr/bin/env python #coding=UTF-8 #默认python编码是ASCII编码 要支持中文 #加上coding=UTF-8的声明 # open()打开文件 r只读 w写入 a追加 r+ w+ a+模式 # a+方式打开文件 指针指向结尾 ,

python学习笔记之面向对象编程特性(二)

面向对象程序设计中的术语对象(Object)基本上可以看做数据(特性)以及由一系列可以存取.操作这些数据的方法所组成的集合.传统意义上的"程序=数据结构+算法"被封装"掩盖"并简化为"程序=对象+消息".对象是类的实例,类的抽象则需要经过封装.封装可以让调用者不用关心对象是如何构建的而直接进行使用. 首先说明一下python编程规范: #!/usr/bin/env python #coding=utf-8 #编程规范,示例如下:   class