Python面试题
闭包
形成闭包的三个必备条件
- 在一个函数中定义一个内置函数
- 内置函数运用了外函数的临时变量
- 外函数的返回值是内函数的引用,相当于执行内部函数一般情况下,在我们的认知当中,如果一个函数结束,函数内部所有的东西都会释放掉,还给内存,局部变量都会消失,但是闭包是另外一种情况,如果外函数在结束的时候发现又自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定内部函数,然后自己再结束
装饰器
原理
- 装饰器的实现是由闭包支撑的
- Python的装饰器本质是一个嵌套函数,它接收被装饰的函数(func)作为参数,并返回一个包装过的函数
- 多个装饰器,封装从上至下,执行从上至下
适用场合
当我们需要给函数添加一个功能,又不想通过修改源代码或者类的继承访问时,可以使用装饰器灵活添加和删除功能
应用场合
- 计算函数的运行时间
- 插入日志
- 事务处理
- 权限验证
讲一讲Python是如何进行内存管理的
- 对象的引用计数机制
- Python动态模型
- 对象是存储在内存中的实体
- 对象名是指向这一对象的引用
- 引用和对象分离,引用可以随时指向另一对象
- 引用计数增加
- 对象被引用
- 引用计数减少
- del删除或者重新调用
- Python动态模型
- 垃圾回收
- Python的某个对象的引用计数降为0的时候可以被回收
- 垃圾回收时,Python不能执行其他任务,当python运行时,会记录其中的分配对象和取消分配对象,当两者差值高于某个阈值时,垃圾回收才会启动
- 分代回收 – 存储越久的对象,越不可能被回收
- 缓存池机制
- 将不用的内存放到缓存池而不是返回给操作系统,用于小块内存的申请和释放
Python2和Python3的区别
- print由关键字变为函数
- python3中使用utf8编码,解决了python2中使用ascii码导致的中文乱码问题
- python3中range和xrange合并成range,本质上是xrange,python2中xrange返回的是一个迭代器,range返回的是一个列表
Python多线程和多进程以及协程
-
进程:对各种资源管理的集合,占用独立的内存空间
-
线程:操作系统调用的最小单位,多线程共享内存空间,python的多线程只能在一个核心上跑,所以Python大多采用协程
-
协程:单线程 缺点和优点
- 优点:高并发+高扩展性+低成本
- 缺点:无法利用多核资源
-
GIL-全局解释器锁
任一时间,只允许一个线程使用解析锁,跟单CPU跑多个程序一个意思,大家都是轮着用的,这叫并发,不叫并行
lambda函数
-
适用场合
函数业务逻辑简单,使代码看起来更加pythonic
-
格式
lambda [参数]:[表达式
深拷贝和浅拷贝的区别
浅拷贝是将对象的引用赋值给另一个对象,因此如果我们在副本中进行修改时会影响源对象
深拷贝是将对象本身复制给另一个对象,这意味着如果对对象的副本进行更改时不会影响源对象
python中运算符
- 算术运算符
- 关系运算符
- 赋值运算符
- 逻辑运算符
- 成员运算符(in not in )
- 身份运算符(is not is) 判断两个对象是否相同
- 位运算符(&|^~)
讲一讲python异常处理机制?
python所有异常的基类都是Exception,捕获异常用try…except… 还可以使用raise手动触发异常
生成器、迭代器和可迭代对象的区别
可直接作用于for循环的对象称为可迭代对象,可迭代对象实现了iter魔法方法,迭代器则是实现iter和next魔法方法的对象,可以显示地获取下一个元素,生成器是特殊的迭代器,生成器返回一个迭代器,生成器中包含yield关键字,相当于一个断点,执行到此返回一个值后暂停,从而实现next取值
is和==的区别
is是身份运算符,判断两个对象是否一样,==是比较操作符,看两个对象的值是否相等
你知道哪些python的模块
time sys os random string re math
Django
django请求生命周期
- 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端
- 请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post,体 现在url之中.
- url经过Django中的wsgi,再经过Django的中间件,最后url到过路由映射表,在路由中一条一条进行匹配,
- 一旦其中一条匹配成功就执行对应的视图函数,后面的路由就不再继续匹配了.
- 视图函数根据客户端的请求查询相应的数据.返回给Django,然后Django把客户端想要的数据做为一个字符串返回给客户端.
- 客户端浏览器接收到返回的数据,经过渲染后显示给用户.
什么是wsgi(web server gateway interface)
web服务网关接口,当一个Http请求过来的时候,就有一个相应的处理函数来进行处理和返回结果,wsgi就是规定了处理函数的输入和输出格式
使用WSGI接口,我们可以将Web服务器端和处理请求的Web框架进行分开,针对不同的需求我们可以开发不同的Web服务器和Web框架,然后自己组合使用、
简单描述浏览器通过WSGI接口请求动态资源的过程
-
服务器的Nginx一直处于监听状态,当客户端的浏览器发来请求后,Nginx根据请求信息进行分析,对于静态请求分发到静态资源返回数据,对于动态资源请求分发到相应的处理端口,计算分析后返回数据
-
程序的WSGI会一直监听某个端口,当监听到数据后,然后请求的数据封装成一个字典对象,然后同时提供一个start_response方法用于处理浏览器请求,返回相应的数据
-
字典对象和start_request方法作为参数,传递给一个实例,该实例一般有wsgi_app(environ,start_response)或者实现了call(self,environ,start_response)方法
-
上述中的实例调用strat_respnose方法返回WSGI中间件,中间件再返回给Nginx,数据最后返回给客户端的浏览器
什么是设计模式
程序中设计模式:大量的开发人员在长期的开发过程中,针对某一类问题,总结出来的通用 的解决方案,程序中使用的设计模式,可以大大提高开发的效率,减少犯错的几率,是他人可以更好的理解代码,代码更加可靠高效
设计模式是一种解决问题的方法模式,常用的是工厂模式和单例模式
class City(Object):
instance = None
def __new__(cls,*args,**kwargs):
if not cls.insatnce:
cls.instance = super().__new__(cls)
return cls.instance
else:
return cls.instance
协程的优势是什么?
在协程之中,调用一个任务类似于Python中调用一个函数一样,消耗的资源少
协程的相互切换只是单纯的操作CPU上下文,因此一秒钟可以切换上百万次
协程的最大优势就是消耗资源少,大量的切换系统也不会产生很大的问题
多线程和多进程运行在哪些场景?
- 计算密集型(多进程):代码没有等待时间,使用多进程,发挥多核性能
- IO密集型(多线程,协程):比如网络收发,文件读写,具有等待时间,优先使用协程,再去考虑线程
全局解析锁是什么?如何解决GIL的问题
全局解析锁(GIL)
- Python代码的执行是由Python虚拟机进行控制,Python语言本身没有GIL问题,是Python虚拟机(Python解析器)的问题
- 在主循环只能有一个线程在执行,每个线程执行的时候需要获取GIL,GIL锁的作用是保证同一时刻只有一个线程在执行代码
多线程和多进程如何通信?
- 多线程通信: queue.Queue()
- 多进程通信:multiprocessing.Queue
- 进程池通信:multiprocessing.Manager().Queue()
如何使用多协程并发的请求网页?
-
使用协程池gevent模块,遇到阻塞,自动切换协程
-
由于IO操作非常耗时,程序经常处于等待状态,比如请求多个网页有时候许哟啊等待,gevent可以自动切换协程
-
遇到阻塞自动切换协程,程序启动时执行Monkey.patch_all()解决,多个协程,可以采用pool管理并发数,限制并发任务数
from gevent import monkey;monkey.patch_all()
from urllib import request
from gevent.pool import Pool
def run_task(url):
print("Visit---->%s"%url)
try:
response = request.urlopen(url)
data = response.read()
except Excecption:
print("error")
return "url%s--->finish"%url
if __name__ == "__main__":
pool = Pool(2)
urls = ["https://github.com/","https://blog.csdn"]
results = pool.map(run_task,urls)
print(results)