面试题
1 def func(a,b=[]):pass 有什么坑
如果在函数的默认参数中设置可变参数,在函数的内部会维护一个列表,供所有调用者使用。
def func(a,b=[]):
b.append(a)
return b
v1 = func(1)
v2 = func(2.[])
v3 = func(3)
print(v1) [1,3]
print(v2) [2]
print(v3) [1,3]
2 写一个带参数的装饰器 满足封闭开发原则,在原代码不动的情况下添加新的功能
应用场景:@classmethod @staticmethod @csrf 用户认证系统
def func1(a):
def func2(func):
def func3(*args,**kwargs):
print(a)
ret = func(*args,**kwargs)
return ret
return func3
return func2
面试2
1 常见的HTTP请求头
content-type
user-agent
connection:keep-alive 保持长连接.
host
2 什么是反射,以及应用场景
根据字符串的形式操作对象的方法
应用场景:
django中间件的处理
可扩展插件
3 可扩展插件是如何实现的
1 把所有插件定义到类中,并且通过基类+异常进行约束,必须包含process方法
2 将类的路径注册到配置文件中
3 根据字符串的形式导入模块(importlib),并且基于反射找到类,然后实例化并执行他的方法
4 单例模式:手写
面试3
1 进程线程协程的区别
进程,计算机的资源分配的最小单位
线程,计算机中cpu调度的最小单位
协程,又称为"微线程",在计算机中不是真实存在,而是程序通过代码伪造出来的
一个进程中有多个线程,一个线程中可以有多个协程,在cpython还有一个GIL,全局解释器锁,由于GIL的存在
导致python中:计算密集型用进程,io密集型用线程(协程)
2 https
什么是http?
超文本传输协议,
基于TCP协议之上创建一个协议,此协议无状态的短连接,
-短连接 一次请求,一次响应之后断开连接
-数据传输格式:请求头和请求体之间通过2个\r\n分隔。请求头和请求头之间通过1个\r\n分隔
浏览器输入ulr
socket.send('POST /index/ http1.1\r\n')
浏览器接收的数据
'200 ok\r\n响应头\r\n\r\n响应体'
什么是Https?
对传输的数据进行了加密
默认端口 443
对称加密, 双方密钥相同
非对称加密 公钥(加密)和私钥(解密)
面试4
1 什么是接口
一个url就是一个接口
2 什么是restful规范
1 用https代替http
2 在URL中有API标识
3 URL中要有版本
4 以前接口CRUD,现在一个URL,根据method不同做不同操作 get post delete put patch
3 什么是DRF(Django REST framework)
他是一个django的组件(app)
它可以帮助我们快速开发遵循restful规范的接口
-csrf
-页面渲染(json)
4 APIView里面有5种方法
get 获取多条数据或者一条数据
post 增加
delete 删除
put 全部更新
patch 局部更新
5 你曾经在使用drf时,视图都继承过那些类
API, 没有提供增删改查的功能,全部需要自己写
ModelViewSet 内置实现了增删改查,无须自己写
6 drf提供了什么功能
1 免除csrftoken的认证
2 提供了一些视图类:APIView, ListAPIView,ModelViewSet, 他的内部帮助我们
写了get/post/put.patch.delete方法,帮助我们可以快速实现增删改查
3 渲染器,页面的渲染
4 序列化(表单验证+序列化)
5 解析器,j解析request.body的数据格式,并赋值到了request.data中
6 版本控制,
面试5
1 跨域
由于浏览器具有同源策略的限制,
限制:在发生Ajax请求时,如果当前浏览器的URL是a.com,页面中向b.com,发送Ajax请求,请求可以正常访问,
但数据回到浏览器时,浏览器就会阻止.
2 解决跨域 CORS
在b.com中设置一个响应头可以解决问题
def book(request):
result = HttpResponse('bbbb')
result['Access-Control-AIIow-Origin'] = "*" 解决跨域
return result
3 补充
真正项目上线后,使用cors解决跨域时,在nginx上设置响应头即可
面试6
python的内存管理机制
python是由C语言开发的,在python的源码中定义了2个重要的结构,分别是pyobject pyVarObject
python中由单个对象组成时,会使用pyobject结构体.创建多个元素组成时,会使用pyVarObject结构体
因为在pyobject内部维护了引入计算器,数据类型,双向链表.
在pyVarObject结构体内部维护了引入计算器,数据类型,双向链表,元素个数
在python中每创建一个对象,首先会进行初始化,(让引入计算器等于1).然后再将对象添加到双向链表中(ref_chain),当我们对
对象重复引用时,会找到对象的引用计算器找到加1.ob_ref_cnt+1, 如果遇到del,会在内存中或双向链表中找到对象,将其引
用计算器将其减1,如果引用计算器减到0,则意味着此对象变成垃圾,销毁系统.
在python内部会有缓存机制或者驻留机制.
python的垃圾回收机制
已引用计数器为主,分代回收和标记清楚为辅,
由于引用计算器无法解决循坏引用的问题,(只有多个元素组成的对象才有出现)
标记清除是每一次创建对象,
会将python所有的对象划分2个不同链表中,(单个,多个),在python内部会定期扫描
由多个元素的链表,如果遇到循坏引用,则让各自的计算器减一.
分代回收:
由于在标记清除,在扫描这个链表时时,他的对象比较多,并且为了设置对象扫描的优先级.设置了分代回收
分别是0代,1代,2代,0代扫描10次,才扫描1次1代,1代扫描10次,才扫描1次2代.