python深浅拷贝 面试_Python面试宝典之基础篇-02

原标题:Python面试宝典之基础篇-02

我觉得你如果正在找工作,我的Python面试宝典几期教程,你一定得花时间看完了!

题目006:说说Python中的浅拷贝和深拷贝。

点评:这个题目本身出现的频率非常高,但是就题论题而言没有什么技术含量。对于这种面试题,在

回答的时候一定要让你的答案能够超出面试官的预期,这样才能

获得更好的印象分。所以回答这个题目的要点不仅仅是能够说出浅拷贝和深拷贝的区别,深拷贝的时候可能遇到的两大问题,还要说出Python标准库对浅拷贝和深拷贝的支持,然后可以说说列表、字典如何实现拷贝操作以及如何通过序列化和反序列的方式实现深拷贝,最后还可以提到设计模式中的原型模式以及它在项目中的应用。

浅拷贝通常只复制对象本身,而深拷贝不仅会复制对象,还会递归的复制对象所关联的对象。深拷贝可能会遇到两个问题:一是一个对象如果直接或间接的引用了自身,会导致无休止的递归拷贝;二是深拷贝可能对原本设计为多个对象共享的数据也进行拷贝。Python通过copy模块中的copy和deepcopy函数来实现浅拷贝和深拷贝操作,其中deepcopy可以通过memo字典来保存已经拷贝过的对象,从而避免刚才所说的自引用递归问题;此外,可以通过copyreg模块的pickle函数来定制指定类型对象的拷贝行为。

deepcopy函数的本质其实就是对象的一次序列化和一次返回序列化,面试题中还考过用自定义函数实现对象的深拷贝操作,显然我们可以使用pickle模块的dumps和loads来做到,代码如下所示。

import pickle

my_deep_copy = lambda obj: pickle.loads(pickle.dumps(obj))

列表的切片操作[:]相当于实现了列表对象的浅拷贝,而字典的copy方法可以实现字典对象的浅拷贝。对象拷贝其实是更为快捷的创建对象的方式。在Python中,通过构造器创建对象属于两阶段构造,首先是分配内存空间,然后是初始化。在创建对象时,我们也可以基于“原型”的对象来创建新对象,通过对原型对象的拷贝(复制内存)就完成了对象的创建和初始化,这种做法其实更加高效,这也就是设计模式中的原型模式。我们可以通过元类的方式来实现原型模式,代码如下所示。

import copy

class PrototypeMeta(type):

"""实现原型模式的元类"""

def __init__(cls, *args, **kwargs):

super().__init__(*args, **kwargs)

# 为对象绑定clone方法来实现对象拷贝

cls.clone = lambda self, is_deep=True: \

copy.deepcopy(self) if is_deep else copy.copy(self)

class Person(metaclass=PrototypeMeta):

pass

p1 = Person()

p2 = p1.clone() # 深拷贝

p3 = p1.clone(is_deep=False) # 浅拷贝

题目007:Python是如何实现内存管理的?

点评:当面试官问到这个问题的时候,一个展示自己的机会就摆在面前了。你要先反问面试官:“你说的是官方的CPython解释器吗?”。这个反问可以展示出你了解过Python解释器的不同的实现版本,而且你也知道面试官想问的是CPython。当然,很多面试官对不同的Python解释器底层实现到底有什么差别也没有概念。所以,

千万不要觉得面试官一定比你强,怀揣着这份自信可以让你更好的完成面试。

Python提供了自动化的内存管理,也就是说内存空间的分配与释放都是由Python解释器在运行时自动进行的,自动管理内存功能极大的减轻程序员的工作负担,也能够帮助程序员在一定程度上解决内存泄露的问题。以CPython解释器为例,它的内存管理有三个关键点:引用计数、标记清理、分代收集。

引用计数:对于CPython解释器来说,Python中的每一个对象其实就是PyObject结构体,它的内部有一个名为ob_refcnt 的引用计数器成员变量。程序在运行的过程中ob_refcnt的值会被更新并藉此来反映引用有多少个变量引用到该对象。当对象的引用计数值为0时,它的内存就会被释放掉。

typedef struct _object {

_PyObject_HEAD_EXTRA

Py_ssize_t ob_refcnt;

struct _typeobject *ob_type;

} PyObject;

以下情况会导致引用计数加1:

对象被创建

对象被引用

对象作为参数传入到一个函数中

对象作为元素存储到一个容器中

以下情况会导致引用计数减1:

用del语句显示删除对象引用

对象引用被重新赋值其他对象

一个对象离开它所在的作用域

持有该对象的容器自身被销毁

持有该对象的容器删除该对象

可以通过sys模块的getrefcount函数来获得对象的引用计数。引用计数的内存管理方式在遇到循环引用的时候就会出现致命伤,因此需要其他的垃圾回收算法对其进行补充。

标记清理:CPython使用了“标记-清理”(Mark and Sweep)算法解决容器类型可能产生的循环引用问题。该算法在垃圾回收时分为两个阶段:标记阶段,遍历所有的对象,如果对象是可达的(被其他对象引用),那么就标记该对象为可达;清除阶段,再次遍历对象,如果发现某个对象没有标记为可达,则就将其回收。CPython底层维护了两个双端链表,一个链表存放着需要被扫描的容器对象(姑且称之为链表A),另一个链表存放着临时不可达对象(姑且称之为链表B)。为了实现“标记-清理”算法,链表中的每个节点除了有记录当前引用计数的ref_count变量外,还有一个gc_ref变量,这个gc_ref是ref_count的一个副本,所以初始值为ref_count的大小。执行垃圾回收时,首先遍历链表A中的节点,并且将当前对象所引用的所有对象的gc_ref减1,这一步主要作用是解除循环引用对引用计数的影响。再次遍历链表A中的节点,如果节点的gc_ref值为0,那么这个对象就被标记为“暂时不可达” (

GC_TENTATIVELY_UNREACHABLE) 并被移动到链表B中;如果节点的gc_ref不为0,那么这个对象就会被标记为“可达“ (GC_REACHABLE),对于”可达“对象,还要递归的将该节点可以到达的节点标记为”可达“;链表B中被标记为”可达“的节点要重新放回到链表A中。在两次遍历之后,链表B中的节点就是需要释放内存的节点。

分代回收:在循环引用对象的回收中,整个应用程序会被暂停,为了减少应用程序暂停的时间,Python 通过分代回收(空间换时间)的方法提高垃圾回收效率。分代回收的基本思想是:对象存在的时间越长,是垃圾的可能性就越小,应该尽量不对这样的对象进行垃圾回收。CPython将对象分为三种世代分别记为0、1、2,每一个新生对象都在第0代中,如果该对象在一轮垃圾回收扫描中存活下来,那么它将被移到第1代中,存在于第1代的对象将较少的被垃圾回收扫描到;如果在对第1代进行垃圾回收扫描时,这个对象又存活下来,那么它将被移至第2代中,在那里它被垃圾回收扫描的次数将会更少。分代回收扫描的门限值可以通过gc模块的get_threshold函数来获得,该函数返回一个三元组,分别表示多少次内存分配操作后会执行0代垃圾回收,多少次0代垃圾回收后会执行1代垃圾回收,多少次1代垃圾回收后会执行2代垃圾回收。需要说明的是,如果执行一次2代垃圾回收,那么比它年轻的代都要执行垃圾回收。如果想修改这几个门限值,可以通过gc模块的set_threshold函数来做到。

题目008:说一下你对Python中迭代器和生成器的理解。

点评:很多人面试者都会写迭代器和生成器,但是却无法准确的解释什么是迭代器和生成器。如果你也有同样的困惑,可以参考下面的回答。

迭代器是实现了迭代器协议的对象。跟其他编程语言不通,Python中没有用于定义协议或表示约定的关键字,像interface、protocol这些单词并不在Python语言的关键字列表中。Python语言通过魔法方法来表示约定,也就是我们所说的协议,而__next__和__iter__这两个魔法方法就代表了迭代器协议。生成器是迭代器的语法升级版本,可以用更为简单的代码来实现一个迭代器。

面试中经常会让面试者写生成斐波那契数列的迭代器,下面给出参考代码,其他的迭代器可以如法炮制。

class Fib(object):

def __init__(self, num):

self.num = num

self.a, self.b = 0, 1

self.idx = 0

def __iter__(self):

return self

def __next__(self):

if self.idx < self.num:

self.a, self.b = self.b, self.a + self.b

self.idx += 1

return self.a

raise StopIteration()

如果用生成器的语法来改写上面的代码,代码会简单优雅很多。

def fib(num):

a, b = 0, 1

for _ in range(num):

a, b = b, a + b

yield a

可以通过for-in循环从迭代器对象中取出值,也可以使用next函数取出迭代器对象中的下一个值。

题目009:正则表达式的match方法和search方法有什么区别?

点评:正则表达式是字符串处理的重要工具,所以也是面试中经常考察的知识点。在Python中,使用正则表达式有两种方式,一种是直接调用re模块中的函数,传入正则表达式和需要处理的字符串;一种是先通过re模块的compile函数创建正则表达式对象,然后再通过对象调用方法并传入需要处理的字符串。如果一个正则表达式被频繁的使用,我们推荐后面这种方式,它会减少频繁编译同一个正则表达式所造成的开销。

match方法是从字符串的起始位置进行正则表达式匹配,返回Match对象或None。search方法会扫描整个字符串来找寻匹配的模式,同样也是返回Match对象或None。

题目010:下面这段代码的执行结果是什么。

def multiply():

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

print([m(100) for m in multiply()])

运行结果:

[300, 300, 300, 300]

上面代码的运行结果很容易被误判为[0, 100, 200, 300]。首先需要注意的是multiply函数用生成式语法返回了一个列表,列表中保存了4个Lambda函数,这4个Lambda函数会返回传入的参数乘以i的结果。需要注意的是这里有闭包(closure)现象,multiply函数中的局部变量i的生命周期被延展了,由于i最终的值是3,所以通过m(100)调列表中的Lambda函数时会返回300,而且4个调用都是如此。

如果想得到[0, 100, 200, 300]这个结果,可以按照下面几种方式来修改multiply函数。

方法一:使用生成器,让函数获得i的当前值。

def multiply():

return (lambda x: i * x for i in range(4))

print([m(100) for m in multiply()])

或者

def multiply():

for i in range(4):

yield lambda x: x * i

print([m(100) for m in multiply()])

方法二:使用偏函数,彻底避开闭包现象。

from functools import partial

from operator import __mul__

def multiply():

return [partial(__mul__, i) for i in range(4)]

print([m(100) for m in multiply()])

温馨提示:Python面试宝典会持续更新,从基础到项目实战的内容都会慢慢覆盖到。虽然每天只更新5个题目,但是每道题扩散出的信息量还是比较大的,希望对找工作的小伙伴所有帮助。

责任编辑:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/489037.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

磁盘挂载基本概念

基本概念PV( 全称 Physical Volume , 物理卷):普通的直接坊问的存储设备&#xff0c;有固定的和可移动的之分&#xff0c;代表性的就是硬盘 VG(全称 Volume Group,卷组):AIX中最大的存储单元&#xff0c;一个卷组由一个或多个PV组成 PP(全称 Physical Partition,物理分区):将PV…

数字孪生白皮书(2019)

▲ 赛迪工业互联网首席研究员袁晓庆博士发布报告来源&#xff1a;赛迪智库以下是白皮书主要内容的PPT&#xff1a;&#xff08;点击放大观看&#xff09;123456789101112131415161718192021222324252627282930未来智能实验室是人工智能学家与科学院相关机构联合成立的人工智能&…

java手动线程池使用_Java手动配置线程池过程详解

线程池中&#xff0c;常见有涉及到的&#xff1a;ExecutorService executorService Executors.newSingleThreadExecutor();ExecutorService executorService1 Executors.newCachedThreadPool();ExecutorService executorService2 Executors.newFixedThreadPool(3);关于Execu…

BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]

传送门 题意&#xff1a;不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换&#xff0c;因为你兑换说明有利可图&#xff0c;是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊&#xff0c;一定比多天的组合好 $f[i]$表示第$i$天最多能得到的钱…

集水井盖板图集07fj02_【干货】住宅通病详细图集(图文详解)

工序节点1建筑物外墙与散水坡、台阶、明沟留沉降缝图示&#xff1a;要求与做法&#xff1a;1、散水坡、台阶、明沟本身按≤6m长度(总长度均分)留沉降缝。2、外墙阴阳角位按450角留沉降缝。3、散水坡与台阶交接处留沉降缝分隔。工序节点2室外地面 伸缩缝图示&#xff1a;要求与…

最新发布!北京市机器人产业创新发展行动方案(2019-2022) “5432”推动北京机器人产业高质量发展...

来源&#xff1a;机器人大讲堂各有关单位&#xff1a;为贯彻《北京市加快科技创新发展智能装备产业的指导意见》&#xff0c;推动北京市机器人产业高质量发展&#xff0c;现将《北京市机器人产业创新发展行动方案&#xff08;2019—2022年&#xff09;》印发给你们&#xff0c;…

php png 输出,PHP直接输出一张图片代码写法

示例代码&#xff1a;public function img(){$img "https://file.zyku.net/p/b197f42c06ffff2e03bfbacee4ce94c4.jpg";$info getimagesize($img);$imgExt image_type_to_extension($info[2], false); //获取文件后缀$fun "imagecreatefrom{$imgExt}";$…

判别分析分为r型和q型吗_电流互感器天天见,但是你真正了解和知道它的一些注意事项吗?...

电流互感器也许你天天见&#xff0c;但是你真正了解电流互感器和它的一些注意事项吗&#xff1f;今天我就带大家一步步分析下电流互感器。一&#xff0c;定义&#xff0c;什么是电流互感器&#xff1f;电流互感器是根据电磁感应原理将一次侧大电流转换成二次侧小电流来测量或计…

LintCode 373: Partition Array

LintCode 373: Partition Array 题目描述 分割一个整数数组&#xff0c;使得奇数在前偶数在后。 样例 给定[1, 2, 3, 4]&#xff0c;返回[1, 3, 2, 4]。 Thu Feb 23 2017 思路 简单题&#xff0c;可以很自然地想到再用一个答案数组&#xff0c;从头到尾遍历一遍&#xff0c;遇到…

刚刚,Science发布2019十大科学突破!

来源&#xff1a;中国生物技术网 北京时间12月20日&#xff0c;《Science》公布了今年的十大突破。“直视”黑洞图片来源&#xff1a;UNIVERSITY OF ARIZONA/INSTITUTE FOR ADVANCED STUDY图片来源&#xff1a;EHT COLLABORATION/CC 4.0巨大的、无处不在的黑洞&#xff0c;在某…

nginx php分离,nginx-php配置动静分离

实验目的&#xff1a;nginx-php配置动静分离实验环境&#xff1a;主机 192.168.88.100 NGINX服务器主机 192.168.88.102 PHP和MYSQL服务器注意&#xff1a;想要手工编译必须安装gcc gcc-c make 这三个插件并且关闭防火墙service firewalld stopsystemctl disable firewalld1.在…

用python分析小说_用Python对哈利波特系列小说进行情感分析

原标题&#xff1a;用Python对哈利波特系列小说进行情感分析准备数据现有的数据是一部小说放在一个txt里&#xff0c;我们想按照章节(列表中第一个就是章节1的内容&#xff0c;列表中第二个是章节2的内容)进行分析&#xff0c;这就需要用到正则表达式整理数据。比如我们先看看 …

模仿u-boot的makefile结构

u-boot&#xff08;2014.04&#xff09;是通过顶层makefile调用各子目录中的makefile来实现整个工程的编译的&#xff0c;实际上子目录的makefile是include进来的。这里仿照这种结构写个模板测试一下。 目录结构&#xff1a; mytest&#xff1a; add&#xff1a; mul&#xff1…

我国机器视觉企业体量偏小,上游零部件占利润大头

来源&#xff1a;仪商网根据中国机器视觉产业联盟(CMVU)调查统计&#xff0c;目前进入中国市场的国际机器视觉企业和中国本土的机器视觉企业(不包括代理商)都已经超过200家&#xff0c;产品代理商超过300家&#xff0c;专业的机器视觉系统集成商超过70家&#xff0c;覆盖全产业…

php 后端 轻量 框架,GitHub - 22cloud/mixphp: 轻量 PHP 框架,基于 Swoole 的常驻内存型 PHP 高性能框架 (开发文档完善)...

高性能 • 轻量级 • 命令行MixPHP 是什么MixPHP 秉承 "普及 PHP 常驻内存型解决方案&#xff0c;促进 PHP 往更后端发展" 的理念而创造&#xff0c;采用 Swoole 扩展作为底层引擎&#xff0c;围绕常驻内存的方式而设计&#xff0c;提供了 Web / Console 开发所需的众…

技术面试问项目难题如何解决的_技术创新 | 降本增效,青海农信社项目小伙刻苦钻研解决联合支架设计难题!...

革新READ随着建筑技术的进步&#xff0c;建筑内部功能和机电系统越来越多样&#xff0c;带来机电管线的数量成倍增加。为节约建筑空间&#xff0c;提高建筑净高&#xff0c;保证系统功能&#xff0c;提升履约品质&#xff0c;越来越多的项目选择采用联合支架的形式将各类管线集…

MYSQL四

-- ########## 01、ER关系 ##########-- ER关系&#xff08;逻辑描述&#xff09; -- A&#xff1a;E---Entity简写&#xff0c;实体&#xff0c;具有相同属性&#xff08;特征&#xff09;的对象归为同一实体 -- Attribute属性&#xff0c;描述实体具有的特征&#xff…

AI研究过于集中狭隘,我们是不是该反思了?

来源&#xff1a;AI科技大本营译者 | 陆离编辑 | 夕颜【导读】2019年是AI领域更加冷静的一年&#xff0c;少了些喧嚣和泡沫&#xff0c;大浪淘沙留下的是经过检验的真正的AI研究者、实践者。但是你也许没有发现&#xff0c;本来被寄予厚望要解决一切“疑难杂症”的AI&#xff0…

svchost占用内存过高_是什么导致你的Java服务器内存和CPU占用过高呢

一、内存占用过高1、造成服务器内存占用过高只有两种情况&#xff1a;内存溢出或内存泄漏(1)内存溢出&#xff1a;程序分配的内存超出物理内存的大小&#xff0c;导致无法继续分配物理内存&#xff0c;出现OOM报错。(2)内存泄漏&#xff1a;不再调用的对象一直占用着内存不释放…

php取不到post数据库,安卓post 数据到php 在写入数据库老是不成功, 数据post不到php...

代码如下安卓端public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);new Thread(){Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);new Thread(){Overridepublic void run(){ArrayList para…