0、前言


最近和几位面试的朋友聊天,部分公司会有笔试环节,而很多中小型公司现在都没有了笔试环节。如果遇到有笔试的公司,一些基础 Python 知识点考查的频率还是很高的。今天,小编就给大家整理了 10 道较为常见的 Python 面试题,以及相应的答案,来帮助小伙伴们更好的了解和学习 Python,也为后续的面试,奠定一定的基础。


1、请简述工作常用的 Python 标准库?


工作中,我常用的 Python 标准库主要有:os、time、random、threading、json 等。

os: 操作系统相关的操作

time: 时间相关业务

random: 随机数相关的操作

threading: 线程相关的业务

json: 数据格式转

工作中,我常用的 Python第三方库主要有:flask、django、requests、openpyxl、pyaudio 等

flask: 轻量级 Web 开发框架,灵活、可扩展性高

django: 一站式 Web 开发框架,功能齐全

requests: 发送 HTTP 请求

openpyxl: 自动化办公相关的逻辑

pyaudio: 音频相关的业务


2、请简述 Python 中赋值、浅拷贝和深拷贝的区别。


(1) 赋值在 Python 中,对象的赋值就是简单的对象引用,如下所示:

a = "可乐python说"
b = a

print(a is b)  # True

通过上面的例子我们可以发现,a 和 b 是一样的,它们指向同一片内存空间,b 不过是 a 的别名,是引用。


赋值操作(包括对象作为参数、返回值)不会开辟新的内存空间,它只是复制了对象的引用。


也就是说除了 b 这个名字之外,没有其他的内存开销,修改了 a,也就影响了 b,同理,修改了 b,也就影响了 a。


(2) 浅拷贝浅拷贝会创建新的对象,其内容并非原对象本身的引用,而是原对象内第一层对象的引用。


浅拷贝可以通过切片、工厂函数、copy 模块中的 copy 函数实现,我们以最后一种来演示:

from copy import copy
a = ["可乐""python""说"]
b = copy(a)
print(a is b)  # False
print(id(a))   # 69524328
print(id(b))   # 69751304
for i in a:
    # 69309456
    # 66912864
    # 69309504
    print(id(i))

for j in b:
    # 69309456
    # 66912864
    # 69309504
    print(id(j))

浅拷贝产生的列表 b 不再是原来的列表 a 了,使用 is 判断可以发现他们不是同一个对象,使用 id 查看,他们也指向不同的内存空间。

但是当我们使用 id(i) for i in a 和 id(j) for j in b 来查看 a 和 b 中元素的地址时,可以发现二者包含的元素的地址是相同的。

这种情况下,修改 a 或者 b 并不会对彼此产生影响。

 

(3) 深拷贝深拷贝只有一种形式,可使用 copy 模块中的 deepcopy() 函数实现。

深拷贝和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素,深拷贝拷贝出来的对象根本就是一个全新的对象,不再与原来的对象有任何的关联。


(4) 注意事项对于非容器类型,如数字、字符串,以及其他的 "原子" 类型,就没有拷贝一说,产生的都是原对象的引用。如果元组变量值包含原子类型对象,即使采用了深拷贝,也只能得到浅拷贝。


3、请简述 Python 中的模块与包。


在 Python 中,模块是搭建程序的一种方式。每一个 Python 代码文件都是一个模块,并且可以引用其他的模块,比如模块中的对象、属性等。一个包含许多 Python 代码的文件夹是一个包,一个包可以包含模块和子文件夹,一般,包中会包含一个 __init__.py 文件。


4、请简述 Python 中的字典与 Json 的区别。


字典是 Python 中的一种数据结构,字典的 key 值只要是 hashable 的数据类型即可;而 json 是一种数据表现形式,一种数据格式,json 中的 key 必须是使用双引号引起来的字符串类型,使用单引号或者不用引号会导致读取数据错误。


5、请简述你对缺省参数的理解。


缺省参数是指在调用函数的时候,没有传入参数的情况下,则使用默认的参数,在调用函数的同时传入参数,所传入的参数就会替代默认参数生效。*args 是不定长参数,它表示输入参数是不确定的,可以是任意多个;**kwargs 是关键字参数,赋值的时候是以键 = 值的方式,参数是可以任意多对;在定义函数的时候不确定会有多少参数会传入时,就可以使用两个参数。


6、请简述 Python 中递归函终止的条件。


递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据条件判断的结果,选择是继续调用自身,还是 return 返回,终止递归。终止的条件如下:(1) 判断递归函数的次数是否达到某一限定值;(2) 判断运算的结果是否达到某个范围等,根据设计的目的来选择。


7、请手写 Python 中的单例代码如下:

class KelePython(object):
    
    __instance = None
    
    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            cls.__instance = object.__new__(cls)
            return cls.__instance
        else:
            return cls.__instance

8、请简述单例模式的应用场景有哪些?


单例模式一般应用在以下场景:(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等,如日志文件,应用配置等;(2)控制资源的情况下,方便资源之间的互相通信,如网站的计数器、应用配置、多线程池、数据库配置、数据库连接池、应用程序的日志应用等。


9、请简述迭代器与生成器的区别。


迭代器:是一个抽象的概念,任何对象,如果它的类有 next 方法和 iter 方法并且返回自己本身的,都是迭代器。


对于 string、list、dict、tuple 等这类容器对象,在后台 for 语句,其实是对容器对象调用 iter() 函数,会返回一个定义了 next()方法的迭代器对象,它在容器中逐个访问容器内元素,在没有后续元素时,next() 会抛出一个 StopIteration 异常。


生成器:是创建迭代器的简单而强大的工具,写起来就像是正规的函数,只是在需要返回数据的时候 使用 yield 语句。


每次 next() 被调用时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)


区别:生成器能做到迭代器能做的所有事,而且因为自动创建了 iter() 和 next() 方法,生成器显得特别简洁,而且生成器也更加高效,使用生成器表达式取代列表解析可以同时节省内存。


除了创建和保存程序状态的自动方法,当生成器终结时,还会自动抛出 StopIteration 异常。


10、请简述同步,异步,阻塞与非阻塞这四个概念的含义。


同步、异步是相对于多任务而言的,关注的是消息通信机制。


同步:多个任务之间按照先后顺序执行,一个任务执行完,下一个任务才能执行。


异步:多个任务之间没有先后顺序,可以同时执行,有时候一个任务可能要在必要的时候,获取另一个同时执行的任务的结果,一般把这种情况称为回调。


举个例子: 你打电话问朋友最近公司还招不招人,如果是同步机制,朋友会说,你稍等,我先问一下人事的同事,然后就跑去问了,没有挂电话,经过一段时间后,朋友就把问到的结果告诉你(返回结果)

而如果是异步通信机制,朋友会说,我先去问一下人事的同事,然后直接挂掉电话,等问到结果后再主动打电话联系你,这里的回电就是上面说的回调。

 

阻塞、非阻塞是相对于代码执行而言的,关注的是程序在等待调用结果时的状态。

 

阻塞:程序执行卡在了某个阶段,调用者在收到调用结果返回之前,当前线程会被挂起,只用拿到调用结果之后才会返回。

 

非阻塞:即使调用者不能立刻得到结果,调用线程也不会被挂起,而是可以继续执行。


举个例子: 你打电话问朋友最近公司还招不招人,朋友会说,我先问一下人事的同事,如果是阻塞式调用,你就会一直在电话前等待,直到等到朋友的回复。而如果是阻塞式调用,你可以不需要一直守在电话前,可以先去忙其他的事情,偶尔过来检查一下朋友有没有回复即可。


11、总结

 

1、扎实的基础,不仅能让我们应付面试,还能为我们以后的进阶赋能。


2、有些知识点官方的描述可能没那么好理解,但是我们结合一些身边的生活例子去理解,也许就没那么难了。


3、不管面结果如何,只要我们多总结,每次都会有新的收获,也能让我们更加清晰地认识自己,查漏补缺。


 

 

 

 

 

欢迎在线答题 python数据分析师(数据分析/python)