当前位置 : 主页 > 网络编程 > 其它编程 >

Python面试:这9个问题你一定要掌握!

来源:互联网 收集:自由互联 发布时间:2023-07-02
作为一个程序员可能或多或少经历过一些技术面试有些是编程语言本身的问题有些是跟工程相关的问题。笔者自己被面试过或者面试过别人可能或多或少经历过一些技术面试有些是编程
作为一个程序员可能或多或少经历过一些技术面试有些是编程语言本身的问题有些是跟工程相关的问题。笔者自己被面试过或者面试过别人可能或多或少经历过一些技术面试有些是编程语言本身的问题有些是跟工程相关的问题。

笔者自己被面试过或者面试过别人今天我们来总结关于Python程序员面试的时候经常被问到的9个问题供大家参考。

1、列表、元组、字典的区别

这个问题应该经常被问到我们在这里详细做个解释。

列表(List)

Python的列表实际上是一个动态数组存储在一个连续的内存区块中随机存取的复杂度是O(1)插入和删除元素时会造成内存块的移动时间复杂度是O(n)。

同时它是一个可变对象当我们对列表进行赋值时获取到的只是它的内存地址如果需要将列表里的内容全部复制给另一个变量需要用到copy浅拷贝和deepcopy深度拷贝。

元组(Tuple)

Python的元组是一个不可变的数据结构它本质上也是一个数组。因为是不可变对象所以Tuple的长度在创建时就是恒定的所以我们也无法对它进行添加和删除元素的操作。不过在Tuple内所包含的对象是可变的。

当我们把包含元组的变量赋值给另一个变量时实际上是在内存中重新申请了一块内存空间用于新建了一个元组。

字典Dict)

Python的字典是一个哈希表根据键值对(Key,Value)直接访问的数据结构。关于哈希函数在这里不多做解析大家可以自行了解。

如果字典在产生哈希冲突时也就是Key遇到重复的时候。Python会通过开放定址法来计算下一个候选位置反复测试最终保证生成的哈希值不会产生冲突。

字典跟列表一样也是可变对象复制内容同样需要用到copy浅拷贝和deepcopy深度拷贝。

2、如何将一个字符串或者数字倒序输出

字符串倒序我们可以利用Python的切片对字符串进行倒序参考如下代码

str1 "长风几万里吹度玉门关"print(str1[::-1])

切片的参数格式: [start_index: stop_index: step]

如果我们不填写切片起止位置参数那么默认是取字符串全部内容当step参数(步长)为负数时字符串会自动从右往左取值-1就是依次取值那么就自然是倒序了。

我们同样可以通过切片的原理对数字进行倒序输出。

# 正整数的情况number 10002new_number int(str(number)[::-1])# 负整数的情况number -10002new_number int(-{0}.format(str(abs(number))[::-1]))

3、谈一下Python的内存管理机制

Python内建了垃圾回收处理机制引用计数是这个机制的一部分。

在Pyhton源码中实际上是用 Py_INCREF(op) 和 Py_DECREF(op) 这两个宏来增加和减少引用计数。

当一个对象被创建、被赋值、被参数传递函数返回之前的时候它的引用计数值(ob_refcnt)都可能会被加1(INC)一直进行累加。

当对象变量失去作用域的时候引用计数的值会减1(DEC)。

当一个对象的引用计数减少到0之后(ob_refcnt为0)Py_DECREF(op)会调用该对象 "析构函数"(del) 将其从内存中释放。

4、什么是Session、COOKIE、Token

Session是一个概念信息存储在服务端。

COOKIE是对Session的一种实现并信息存储在客户端浏览器。

因为HTTP协议无状态的特性以至于我们需要在浏览器和服务端之间建立一个用于识别用户身份和详细信息的凭证这个凭证可以是COOKIE、Token任意一种。

当用户登陆成功时我们可以将其的身份凭证在服务端生成一个Session信息保存在文件数据库或者内存里通常Session会有一个Session id。

因为访问服务端Session 信息需要用到Session id所以通常情况下我们将Session id存在COOKIE里。

COOKIE其实信息在用户登陆产生Session信息之后再将Session id或者别的附加信息返回给客户端由客户端存储在本地文件里。

当浏览器向服务端发起请求时会带着COOKIE里的Session id访问服务端服务端根据Session id找到存储好的Session信息如果信息能找到并且内容无误即视为访问有效。

COOKIE除了存储Session id外也可以存储其他非敏感的信息例如用户昵称头像等提供给浏览器直接使用而不用每次都从服务端去拿。

关于Token实际上用在基于RESTAPI相关的服务里比较多。

它的认证机制是当用户登陆后服务端算出一个Token信息存储在服务端并返回给客户端内容通常包含 用户id当前时间戳签名和其他信息。

Token在客户端一般存放于localStorage、COOKIE、或sessionStorage中。在服务器一般存于数据库中。

当客户端再次请求服务端时会从本地拿到Token信息并放在headers中服务端收到请求会自动去headers里拿到Token进行解析以用于识别用户身份。

5、GET和POST的区别和作用

GET和POST在本质上没有区别HTTP协议并没有规定GET和POST传输数据长度的限制。

唯一的限制可能存在于服务端的服务程序和浏览器。

通常在 Nginx或者各种WebServer服务程序里会有定义GET和POST传输最大长度的限制。

而GET提交的数据长度限制通常取决于浏览器每种浏览器的限制不一样。

在HTTP协议中使用什么样的Method和数据如何传输其实没有相互的关系在绝大多数的WebServer里。GET和POST提交的数据其实都在BODY区域内我们既可以通过GET来传输文件也可以通过POST来传输文件。

之所以通常定义GET用来获取数据POST用来提交数据是因为GET请求是幂等的POST请求不是。

幂等性是指一次和多次请求某一个资源应该具有同样的副作用。简单来说意味着对同一URL的多个请求应该返回同样的结果。

基于幂等的原则我们用GET进行数据的添加修改删除时会有副作用因为在网络情况不好的时候GET会自动尝试重试增加了重复操作数据的风险。而用它获取数据就不会存在这样的风险因为我们哪怕对一个资源请求100万次它还是不会改变。

这个问题看面试官的技术水准如果面试官愿意跟你聊得比较深入那你可以这么回答。如果面试官自己心里也是一些标准答案的话那建议只回答GET用于获取数据POST用于提交数据。

另外DELETE方法其实也是幂等的哪怕你删除100万次数据其实也只会被删除一次。

6、什么是Python的装饰器

Python的装饰器本质上也是一个函数它的用处是可以让其他函数不做太多代码变动的情况下增加装饰器函数相关的功能。

先来看看装饰器的实现和应用。

file

以上我们实现了一个极简的Python装饰器在fun1函数运行开始和结束的时候打印日志通过这个例子我们可以发现实际上Python的装饰器帮我们简化了调用代码如果不用装饰器那以上代码可以这样写。

file

以上代码会显式的通过log函数去调用func1函数不便于理解也破坏了代码调用的顺序不够优雅。如果我需要给fun1前面加上10多个装饰器的话那得把这个调用关系写上十多次在阅读理解上来看基本就是灾难。

Python的装饰器通常用于但不限于以下场合。

  • 日志打印
  • 性能测试
  • 数据库事务处理
  • 权限校验
  • 缓存处理

总结起来Pyhton装饰器的用处是为了让我们更好的复用代码在实现相同功能代码的情况下采用更符合人类理解的代码结构。

其实Python的装饰器就是JAVA语言中的AOP编程面向切片。

7、Python的全局锁、进程、线程、协程的概念

Python的全局锁是为了保证线程安全而做的妥协简单的说就是不管是几个核的CPU也只能在同时间运行一个线程。IO密集型运算多线程还勉强能用如果是CPU密集型的那Python的多线程几乎没什么卵用。

如果要利用CPU多核的优势可以用到进程在Pyhton中的multiprocessing模块来处理这个问题每个计算任务都会单独起一个Python进程让任务运行在独立的解释器环境中提高运算效率。

而协程的概念是在于线程和进程在CPU用户态和内核态之间进行切换时会产生大量的性能开销。

在这种情况下协程或者叫微线程的概念应运而生。

在Python3.5中之后用async/await关键字来处理协程。

它的优点是

没有线程之间切换切换的开销。

没有线程锁的机制因为只有一个线程不存在共享变量加锁的情况进一步提升了效率。

8、列表推导和字典推导

# 列表推导list1 [i for i in range(5)]# 字典推导dict1 {k:v for k,v in dict.items()}# 集合推导set1 {x*2 for x in [1,2]}

列表推导、字典推导、集合推导都是Python的特性字典推导在Python2.7之后才有。

这三种推导方式的作用都是可以通过已有的数据序列构建另一个新的数据序列的结构体从代码可读性和收敛的角度来讲是很有必要的避免了繁复琐碎的代码写法。

9、生成器

# 构造生成器x (i for i in range(10))# 输出x

我们可以通过以上代码看到生成器的格式和列表推导格式很像唯一区别是把方括号换成了圆括号通过生成器生成出来的对象不再是一个列表而是一个生成器对象。

生成器generator的作用是当我们要产生一个很长的序列不一定马上用到它那么我们就没必要再生成它的时候就开辟很大一块内存空间而是先声明一个对象告诉它我需要一块很大的内存空间但是等到我用的时候再挨个去产生就行了这个在其他语言里面有个词叫做“惰性求值”大家望文思意即可。

我们可以直接用 for循环去遍历生成器对象依次取出值。

关于这9个面试的问题就先讲到这篇幅所限我们其实讲得不够深入因为如果要深入的讲这里的每一个知识点都可以花上一整章来详细的说不过我觉得大家可以根据这些知识点自行去了解和实践更多的细节。

程序员面试对于面试官来说其实不是你能答对多少问题而是你回答的问题质量是否说中了他所认同的那一部分我们对于每一个知识点掌握得越详细说中对方认同的部分就越多成功率就越高。

文源网络仅供学习之用侵删。

在学习Python的道路上肯定会遇见困难别慌我这里有一套学习资料包含40本电子书800个教学视频涉及Python基础、爬虫、框架、数据分析、机器学习等不怕你学不会 https://shimo.im/docs/JWCghr8prjCVCxxK/ 《Python学习资料》

关注公众号【Python圈子】优质文章每日送达。

file

网友评论