面试8
1. Http协议?
Http协议就是一个传输数据格式。
我原来学习django框架,从socket服务端开始学起。
自己创造了一个socket服务器来充当:网站。
浏览器当socket客户端。
更清楚的明白到底http协议是什么?
- 请求头 请求头
- 响应头 响应头
一次请求响应后,断开连接。
2. 常见请求头
3. 常见的请求体?
Form表单提交:
POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\nusername=alex&password=123&...
Ajax请求:
POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\nusername=alex&password=123&...
POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\n{“username”:"alex","password":123}
补充:django中获取请求体
- request.POST
- request.body
4. django请求生命周期
- wsgi, 他就是socket服务端,用于接收用户请求并将请求进行初次封装,然后将请求交给web框架(Flask、Django)
- 中间件,帮助我们对请求进行校验或在请求对象中添加其他相关数据,例如:csrf、request.session
- 路由匹配
- 视图函数,在视图函数中进行业务逻辑的处理,可能涉及到:orm、templates => 渲染
- 中间件,对响应的数据进行处理。
- wsgi,将响应的内容发送给浏览器。
5. 中间件
- 5个方法
- 应用场景:
- 登录认证,不再需要在每个函数中添加装饰器
- 权限,当用户登录时候获取当前用户所有权限并放入session,然后再次访问其他页面,获取当前url并在session中进行匹配。如果没有匹配成功,则在中间件返回“无权访问”
- 跨域,
- jsonp,动态创建一个script标签。
- cors,设置响应头
应用:本地开始前后端分离的时使用。
6. ORM操作
- only
- defer
- seleted_related
- prefetch_related
示例:
class Depart(models.Model): 5个部门
title = models.CharField(...)
class User(models.Model): 10个用户
name = models.CharField(...)
email = models.CharField(...)
dp = models.FK(Depart)
1.以前的你:11次单表查询
result = User.objects.all()
for item in result:
print(item.name,item.dp.title)
2. seleted_related,主动做连表查询(1次链表)
result = User.objects.all().seleted_related('dp')
for item in result:
print(item.name,item.dp.title)
问题:如果链表多,性能越来越差。
3. prefetch_related:2次单表查询
# select * from user ;
# 通过python代码获取:dp_id = [1,2]
# select * from depart where id in dp_id
result = User.objects.all().prefetch_related('dp')
for item in result:
print(item.name,item.dp.title)
赠送:
数据量比较大,不会使用FK,允许出现数据冗余。
7. django rest framework的作用?
快速搭建基于restful规范的接口。
8. 你理解的 restful 规范?
restful是一个规范,规定API如何编写,通过他可以让我们api更加简洁可维护。
如,最直观的:
method:
- get
- post
- put
- delete
原来都是url中设置的。
除此之外:
- api
- 版本
- 名词
- 条件
- 状态码
- 返回值
- 错误信息
- hypermedia link
9. django rest framework组件:
- 访问频率控制原理:
匿名:
1.1.1.1:[时间,时间,时间,时间,]
登录:
user:[时间,时间,时间,时间,]
默认将访问记录放在缓存中:redis/memcached
- 序列化
from rest_framework.serializers import Serializer
class XX(Serializer):
pass
ser =XX(queryset,many=True) # ListSerializer对象
ser =XX(obj, many=False) # XX对象
- 列表生成式
- 根据字符串的形式,自动导入模块并使用反射找到模块中的类【参考:s9day108】。
1. OSI 7层模型 *****
2. 三次握手、四次挥手? ******
3. TCP和UDP区别?************
4. 路由器和交换机的区别?**********
5. ARP协议?
6. DNS解析?
7. Http和Https?
8. 进程、线程、协程区别?************
9. GIL锁 *********
10. 进程如何进程共享? **************
2. twisted是什么以及和requests的区别?
requests是一个Python实现的可以伪造浏览器发送Http请求的模块。
- 封装socket发送请求
twisted是基于事件循环的异步非阻塞网络框架。
- 封装socket发送请求
- 单线程完成并发请求
PS: 三个相关词
- 非阻塞:不等待
- 异步:回调
- 事件循环:一直循环去检查状态。
2. Scrapy框架
- 组件以及执行流程?
- 引擎找到要执行的爬虫,并执行爬虫的 start_requests 方法,并的到一个 迭代器。
- 迭代器循环时会获取Request对象,而request对象中封装了要访问的URL和回调函数。
- 将所有的request对象(任务)放到调度器中,用于以后被下载器下载。
- 下载器去调度器中获取要下载任务(就是Request对象),下载完成后执行回调函数。
- 回到spider的回调函数中,
yield Request()
yield Item()
redis 实现队列 先进先出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import scrapy_redis import redis # 先进先出队列 class FifoQueue( object ): def __init__( self ): self .server = redis.Redis(host = '140.143.227.206' ,port = 8888 ,password = 'beta' ) def push( self , request): """Push a request""" self .server.lpush( 'USERS' , request) def pop( self , timeout = 0 ): """Pop a request""" data = self .server.rpop( 'USERS' ) return data # [33,22,11] q = FifoQueue() q.push( 11 ) q.push( 22 ) q.push( 33 ) print (q.pop()) print (q.pop()) print (q.pop()) |
redis 栈 后进先出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import redis # 后进先出 栈 class LifoQueue( object ): """Per-spider LIFO queue.""" def __init__( self ): self .server = redis.Redis(host = '140.143.227.206' ,port = 8888 ,password = 'beta' ) def push( self , request): """Push a request""" self .server.lpush( "USERS" , request) def pop( self , timeout = 0 ): """Pop a request""" data = self .server.lpop( 'USERS' ) return # [33,22,11] |
redis实现优先队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import redis # 根据优先级队列 从小到大一个个去取 conn = redis.Redis(host = '140.143.227.206' ,port = 8888 ,password = 'beta' ) # conn.zadd('score',alex=79, oldboy=33,eric=73) # # print(conn.keys()) v = conn.zrange( 'score' , 0 , 8 ,desc = True ) print (v) pipe = conn.pipeline() pipe.multi() # zremrangebyrank 根据排序去取值 pipe.zrange( "score" , 0 , 0 ).zremrangebyrank( 'score' , 0 , 0 ) results, count = pipe.execute() print (results,count) |
爬取10组图片

""" 协程+IO切换 pip3 install gevent gevent内部调用greenlet(实现了协程)。 """ from gevent import monkey; monkey.patch_all() import gevent import requests def func(url): response = requests.get(url) print(response) urls = [ 'http://www.baidu.com/', 'https://www.cnblogs.com/', 'https://www.cnblogs.com/news/', 'https://cn.bing.com/', 'https://stackoverflow.com/', ] spawn_list = [] for url in urls: spawn_list.append(gevent.spawn(func, url)) gevent.joinall(spawn_list)

""" 基于事件循环的异步非阻塞模块:Twisted """ from twisted.web.client import getPage, defer from twisted.internet import reactor def stop_loop(arg): reactor.stop() def get_response(contents): print(contents) deferred_list = [] url_list = [ 'http://www.baidu.com/', 'https://www.cnblogs.com/', 'https://www.cnblogs.com/news/', 'https://cn.bing.com/', 'https://stackoverflow.com/', ] for url in url_list: deferred = getPage(bytes(url, encoding='utf8')) deferred.addCallback(get_response) deferred_list.append(deferred) dlist = defer.DeferredList(deferred_list) dlist.addBoth(stop_loop) reactor.run()
单例模式
1 2 3 4 5 6 7 8 9 10 | class Singleton( object ): __instance = None def __new__( cls , age, name): #如果类数字能够__instance没有或者没有赋值 #那么就创建一个对象,并且赋值为这个对象的引用,保证下次调用这个方法时 #能够知道之前已经创建过对象了,这样就保证了只有1个对象 if not cls .__instance: cls .__instance = object .__new__( cls ) return cls .__instance |
装饰器
map 函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | # 补充的代码量请控制在 30 ⾏以内,并注明代码的时间和空间复杂度 expect = { "交易所" : { "中国外汇交易中⼼" : {}, "聚合交易所" : {}, "森浦Quebee" : {} }, "交易模式" : { "报价驱动模式" : { "可执⾏持续报价(ESP)" : {} } } } def convert_format(input_list, parent): tree = {} for item in input_list: if item.get( "parent" , "") = = parent: tree[item[ "name" ]] = convert_format(input_list, item[ "name" ]) return tree # 空间复杂为递归的深度 n3 if __name__ = = '__main__' : input_list = [ { "parent" : "交易所" , "name" : "中国外汇交易中⼼" }, { "name" : "交易所" }, { "parent" : "交易所" , "name" : "聚合交易所" }, { "parent" : "交易所" , "name" : "森浦Quebee" }, { "name" : "交易模式" }, { "parent" : "交易模式" , "name" : "报价驱动模式" }, { "parent" : "报价驱动模式" , "name" : "可执⾏持续报价(ESP)" } ] output = convert_format(input_list, "") print (output) expect = { "交易所" : { "中国外汇交易中⼼" : {}, "聚合交易所" : {}, "森浦Quebee" : {} }, "交易模式" : { "报价驱动模式" : { "可执⾏持续报价(ESP)" : {} } } } assert (output = = expect) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理