题目001: 在Python中如何实现单例模式。点评:这个题目在面试中出现的频率极高,因为它考察的不仅仅是单例模式,更是对Python语言到底掌握到何种程度,建议大家用装饰器和元类这两种方式来实现单例模式,因为这两种方式的通用性最强,而且也可以顺便展示自己对装饰器和元类中两个关键知识点的理解。

方法一:使用装饰器实现单例模式。

from functools import wraps

def singleton(cls):

"""单例类装饰器"""

instances = {}

@wraps(cls)

def wrapper(*args, **kwargs):

if cls not in instances:

instances[cls] = cls(*args, **kwargs)

return instances[cls]

return wrapper

@singleton

class President:

pass扩展:装饰器是Python中非常有特色的语法,用一个函数去装饰另一个函数或类,为其添加额外的能力。通常通过装饰来实现的功能都属横切关注功能,也就是跟正常的业务逻辑没有必然联系,可以动态添加或移除的功能。装饰器可以为代码提供缓存、代理、上下文环境等服务,它是对设计模式中代理模式的践行。在写装饰器的时候,带装饰功能的函数(上面代码中的wrapper函数)通常都会用functools模块中的wraps再加以装饰,这个装饰器最重要的作用是给被装饰的类或函数动态添加一个__wrapped__属性,这个属性会将被装饰之前的类或函数保留下来,这样在我们不需要装饰功能的时候,可以通过它来取消装饰器,例如可以使用President = President.__wrapped__来取消对President类做的单例处理。需要提醒大家的是:上面的单例并不是线程安全的,如果要做到线程安全,需要对创建对象的代码进行加锁的处理。在Python中可以使用threading模块的RLock对象来提供锁,可以使用锁对象的acquire和release方法来实现加锁和解锁的操作。当然,更为简便的做法是使用锁对象的with上下文语法来进行隐式的加锁和解锁操作。

方法二:使用元类实现单例模式。

class SingletonMeta(type):

"""自定义单例元类"""

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

cls.__instance = None

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

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

if cls.__instance is None:

cls.__instance = super().__call__(*args, **kwargs)

return cls.__instance

class President(metaclass=SingletonMeta):

pass扩展:Python是面向对象的编程语言,在面向对象的世界中,一切皆为对象。对象是通过类来创建的,而类本身也是对象,类这样的对象是通过元类来创建的。我们在定义类时,如果没有给一个类指定父类,那么默认的父类是object,如果没有给一个类指定元类,那么默认的元类是type。通过自定义的元类,我们可以改变一个类默认的行为,就如同上面的代码中,我们通过元类的__call__魔术方法,改变了President类的构造器那样。

关于单例模式,在面试中还有可能被问到它的应用场景。通常一个对象的状态是被其他对象共享的,就可以将其设计为单例,例如项目中使用的数据库连接池对象和配置对象通常都是单例,这样才能保证所有地方获取到的数据库连接和配置信息是完全一致的;而且由于对象只有唯一的实例,因此从根本上避免了重复创建对象造成的时间和空间上的开销,也避免了对资源的多重占用。再举个例子,项目中的日志操作通常也会使用单例模式,这是因为共享的日志文件一直处于打开状态,只能有一个实例去操作它,否则在写入日志的时候会产生混乱。

题目002:不使用中间变量,交换两个变量a和b的值。点评:典型的送人头的题目,在其他编程语言中不使用中间变量交换两个变量的值可以使用异或运算,Python中还可以通过内置的字节码指令直接交换两个变量的值。

方法一:

a = a ^ b

b = a ^ b

a = a ^ b

方法二:

a, b = b, a扩展:需要注意,a, b = b, a这种做法其实并不是元组解包,虽然很多人都这样认为。Python字节码指令中有ROT_TWO指令来支持这个操作,类似的还有ROT_THREE,对于3个以上的元素,如a, b, c, d = b, c, d, a,才会用到创建元组和元组解包。想知道你的代码对应的字节码指令,可以使用Python标准库中dis模块的dis函数来反汇编你的Python代码。

题目003:写一个删除列表中重复元素的函数,要求去重后元素相对位置保持不变。点评:这个题目在初中级Python岗位面试的时候经常出现,题目源于《Python Cookbook》这本书第一章的第10个问题,有很多面试题其实都是这本书上的原题,所以建议大家有时间的话好好研读一下这本书。

def dedup(items):

no_dup_items = []

seen = set()

for item in items:

if item not in seen:

no_dup_items.append(item)

seen.add(item)

return no_dup_items

当然,也可以像《Python Cookbook》书上的代码那样,把上面的函数改造成一个生成器。

def dedup(items):

seen = set()

for item in items:

if item not in seen:

yield item

seen.add(item)扩展:由于Python中的集合底层使用哈希存储,所以集合的in和not in成员运算在性能上远远优于列表,所以上面的代码我们使用了集合来保存已经出现过的元素。集合中的元素必须是hashable对象,因此上面的代码在列表元素不是hashable对象时会失效,要解决这个问题可以给函数增加一个参数,该参数可以设计为返回哈希码或hashable对象的函数。

题目004:假设你使用的是官方的CPython,说出下面代码的运行结果。点评:下面的程序对实际开发并没有什么意义,但却是CPython中的一个大坑,这道题旨在考察面试者对官方的Python解释器到底了解到什么程度。

a, b, c, d = 1, 1, 1000, 1000

print(a is b, c is d)

def foo():

e = 1000

f = 1000

print(e is f, e is d)

g = 1

print(g is a)

foo()

结果:

True False

True False

True

上面代码中a is b的结果是True但c is d的结果是False,这一点的确让人费解。这个结果是因为CPython出于性能优化的考虑,把频繁使用的整数对象用一个叫small_ints的对象池缓存起来造成的。small_ints缓存的整数值被设定为[-5, 256]这个区间,也就是说,如果使用CPython解释器,在任何引用这些整数的地方,都不需要重新创建int对象,而是直接引用缓存池中的对象。如果整数不在该范围内,那么即便两个整数的值相同,它们也是不同的对象。

CPython底层为了进一步提升性能还做了一个设定:对于同一个代码块中值不在small_ints缓存范围之内的整数,如果同一个代码块中已经存在一个值与其相同的整数对象,那么就直接引用该对象,否则创建新的int对象。需要大家注意的是,这条规则对数值型适用,但对字符串则需要考虑字符串的长度,这一点可以自行证明。扩展:如果你用PyPy(另一种Python解释器实现,支持JIT,对CPython的缺点进行了改良,在性能上优于CPython,但对三方库的支持略差)来运行上面的代码,你会发现所有的输出都是True。

题目005:Lambda函数是什么,举例说明的它的应用场景。点评:这个题目主要想考察的是Lambda函数的应用场景,潜台词是问你在项目中有没有使用过Lambda函数,具体在什么场景下会用到Lambda函数,借此来判断你写代码的能力。因为Lambda函数通常用在高阶函数中,主要的作用是通过传入或返回函数实现代码的解耦合。

Lambda函数也叫匿名函数,它功能简单用一行代码就能实现的小型函数。Python中的Lambda函数只能写一个表达式,这个表达式的执行结果就是函数的返回值,不用写return关键字。Lambda函数因为没有名字,所以也不会跟其他函数发生命名冲突的问题。

面试的时候有可能还会考你用Lambda函数来实现一些功能,也就是用一行代码来实现题目要求的功能,例如:用一行代码实现求阶乘的函数,用一行代码实现求最大公约数的函数等。

fac = lambda x: __import__('functools').reduce(int.__mul__, range(1, x + 1), 1)

gcd = lambda x, y: y % x and gcd(y % x, x) or x

Lambda函数其实最为主要的用途是把一个函数传入另一个高阶函数(如Python内置的filter、map等)中来为函数做解耦合,增强函数的灵活性和通用性。下面的例子通过使用filter和map函数,实现了从列表中筛选出奇数并求平方构成新列表的操作,因为用到了高阶函数,过滤和映射数据的规则都是函数的调用者通过另外一个函数传入的,因此这filter和map函数没有跟特定的过滤和映射数据的规则耦合在一起。

items = [12, 5, 7, 10, 8, 19]

items = list(map(lambda x: x ** 2, filter(lambda x: x % 2, items)))

print(items) # [25, 49, 361]

当然,用列表的生成式来实现上面的代码更加简单明了,如下所示。

items = [12, 5, 7, 10, 8, 19]

items = [x ** 2 for x in items if x % 2]

print(items) # [25, 49, 361]温馨提示:Python面试宝典会持续更新,从基础到项目实战的内容都会慢慢覆盖到。虽然每天只更新5个题目,但是每道题扩散出的信息量还是比较大的,希望对找工作的小伙伴所有帮助。你的点赞、收藏和评论都是我继续创建的动力,请不要吝惜你的赞美。

python面试秘诀_Python面试宝典之基础篇-01相关推荐

  1. python多线程并发_Python进阶记录之基础篇(二十四)

    回顾 在Python进阶记录之基础篇(二十三)中,我们介绍了进程的基本概念以及Python中多进程的基本使用方法.其中,需要重点掌握多进程的创建方法.进程池和进程间的通信.今天我们讲一下Python中 ...

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

    原标题:Python面试宝典之基础篇-02 我觉得你如果正在找工作,我的Python面试宝典几期教程,你一定得花时间看完了! 题目006:说说Python中的浅拷贝和深拷贝. 点评:这个题目本身出现的 ...

  3. python语言面试基础_Python面试宝典之基础篇-04

    Python面试宝典之基础篇-04 发布时间:2020-08-19 02:59:03 来源:ITPUB博客 阅读:101 接着更新Python常见的面试题! 题目016:写一个函数,给定矩阵的阶数n, ...

  4. python 有放回随机抽取_Python面试宝典之基础篇-08

    原标题:Python面试宝典之基础篇-08 题目36:如何使用random模块生成随机数.实现随机乱序和随机抽样? 点评:送人头的题目,因为Python标准库中的常用模块应该是Python开发者都比较 ...

  5. python程序员面试算法宝典 pdf_Python面试宝典之基础篇3

    Python面试宝典之基础篇-03 题目011:Python中为什么没有函数重载? 点评:C++.Java.C#等诸多编程语言都支持函数重载,所谓函数重载指的是在同一个作用域中有多个同名函数,它们拥有 ...

  6. 0基础python入门书籍 excel_【曾贤志】从零基础开始用Python处理Excel数据 - 第1季 基础篇...

    =====[曾贤志]从零基础开始用Python处理Excel数据 第1季 基础篇====== 1-1 什么是python? .mp4 1-2 为什么要学习用Python处理Excel表格? .mp4 ...

  7. mysql经典总结文章_MySQL基础篇(01):经典实用查询案例,总结整理

    MySQL基础篇(01):经典实用查询案例,总结整理 发布时间:2020-02-26 22:25:21 来源:51CTO 阅读:244 作者:知了一笑 本文源码:GitHub·点这里 || GitEE ...

  8. 视觉slam学习|基础篇01

    系列文章目录 SLAM基础篇01 SLAM基础篇02 目录 系列文章目录 前言 SLAM是干什么的? SLAM的数学建模 机器人学基础 齐次矩阵 关于旋转的表示:旋转向量.欧拉角.四元数 李群和李代数 ...

  9. 自然语言处理——基础篇01

    自然语言处理--基础篇01 一.什么是自然语言处理? 二.自然语言处理的难点与特点? 三.语言模型 四.NLP的常见任务类型 1. 中文分词 2. 子词切分(Subword) 3. 句法分析 4. 语 ...

最新文章

  1. spring源码学习一
  2. windows远程连接报错--“发生身份验证错误。要求的函数不受支持”
  3. linux常用命令:系统目录说明及命令ls,cp,touch,history,gparted分区
  4. 机器阅读理解 / 知识库 / 深度学习 / 对话系统 / 神经机器翻译 | 本周值得读
  5. Linux加密框架 crypto 算法模板 HMAC模板举例
  6. 【OJ1768】最大子矩阵
  7. 使用Sigar做后台服务器管理时,遇到的linux上的问题
  8. 与用户交互、格式化输出、基本运算符
  9. 【笔记整理】通信原理第二章复习——随机信号分析
  10. html广告加图片,网站广告图片右下角加上“广告”水印标识代码
  11. 2019上半年个人成长复盘
  12. littleVGL开发(8):消息弹窗控件(lv_mbox)
  13. 大四学年软件公司实习感悟
  14. 谷歌表格_您应该知道的5种Google表格功能
  15. 微机原理_微处理器架构
  16. 数据太大,记事本打不开怎么办?
  17. 基因数据处理88之vcf2omim得到omim和dbSnpId信息
  18. Activiti源码解读之TaskService
  19. JS 键盘事件、触摸事件
  20. bl wn810a linux驱动下载,bl wn810a驱动下载-BL-WN810A驱动 1.0 官方版 - 河东下载站

热门文章

  1. Terminal和Vim在Mac os和Linux系统下Solarized的配色配置
  2. 照片怎么裁剪多余部分?如何在线裁剪图片?
  3. 怎样用Photoshop做出爆炸效果
  4. 全球电子商务交易预计将在2022年假日季增长15%,消费者情绪乐观
  5. php生成word设置纸张,PHP生成Word文档的方法
  6. ssh远程登陆阿里云服务器ECS
  7. Android Security boot
  8. 小学计算机社团应该学什么,小学计算机社团活动工作计划
  9. 2020 11-12 用SPSS做中国地图
  10. 创建用户定义的数据类型