Python面试的100多题之61-90(详细版)
61、解释一下http协议
http是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。
HTTP协议的主要特点可概括如下:
- 支持客户/服务器模式
- 简单快捷:客户向服务器请求服务时,只需传送请求方法和路径。请求方法行常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
- 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由content-type加以标记
- 无链接:无链接的含义是限制每次链接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开链接。采用这种方式可以节省传输时间。
- 无状态:HTTP协议是无状态。无状态是指协议对事务处理没有记忆能力。缺少状态意味着:如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接的传送的数据量增大。另一方面,在服务器不需要先前信息时,它的应答就较快。
62、解释下HTTP请求头和常见响应状态码。
- Accpet:指浏览器或其他客户可以接受的MIME文件格式。可以根据它判断并返回适当的文件格式。
- Accpet-Charset:指出浏览器可以接受的字符编码。英文浏览器的默认值是ISO-8859-1
- Accept-Language:指出浏览器可以接受的语言种类,如en或en-us,指英语。
- Accept-Encoding:指出浏览器可以接受的编码方式。编码方式不同文件格式,它是为了压缩文件并加速文件传递速度。浏览器在接收到Web响应之后解码。然后再检查文件格式。
- Cache-control:设置关于请求被代理服务器存储的相关选项。一般用不到。
- Connection:用来告诉服务器是否可以维持固定的HTTP连接。HTTP/1.1使用keep-alive为默认值,这样,当浏览器需要多个文件时(比如一个html文件和相关的图形文件)不需要每次都建立连接。
- content-type:用来表明request的内容类型,可以用HttpServiceRequest的getContentType()方法取得。
- cookie:浏览器用这个属性向服务器发送cookie。cookie是浏览器中积存的小型数据体,它可以记载和服务器相关的用户信息,也可以用来实现会话功能。
状态码有三位数字组成,第一个数字定义了响应的类别。且5种可能取值:
- 1xx:指示信息——表示请求已拒收,继续处理
- 2xx:成功——表示请求已被成功接受、理解、接受
- 3xx:重定向——要完成请求必须进行更近一步的擦怄走
- 4xx:客户端错误——请求有语法错误或请求无法实现
- 5xx:服务器端错误——服务器未能实现合法的请求
常见状态代码、状态描述、说明:
- 200 ok //客户端请求成功
- 400 bad request //客户端请求有语法错误,不能被服务器所理解
- 401 unauthorized //请求未经授权,这个状态代码必须和www-Authenticate报头域一起使用
- 403 forbiden. // 服务收到请求,但是拒绝提供服务
- 404 Not found。 //请求资源不存在,eg:输入了错误的url
- 500 Internal Server Error. //服务器发生不可预期的错误
- 503. Server Unavaliable. //服务器当前不能处理客户端的请求,一段时间后可能会恢复正常。
63、请简单说明数据中视图的作用
- 数据库视图隐藏了数据的复杂性
- 数据库视图有利于控制用户对表中某些列的访问
- 数据库视图使用户查询变得简单。
64、列举您使用过的python网络爬虫所用到的网络数据包
requests、urllib等等。
65、列举您使用过的Python网络爬虫所用到的解析数据包
Beautiful Soup pyquey. Xpath. lxml。
65、python语言中enumerate的意思是?
对一个可迭代/可遍历的对象,enumerate将其组成一个索引序列,利用它可以同时获得索引和值,enumerate多用于在for循环中得到的计数。
66、unix 下定时任务的使用
67、写出在网络爬虫爬取数据的过程中,遇到反爬虫问题的解决方案:
- 通过header反爬虫:解决策略,伪造headers
- 基于用户行为反爬虫:动态变化爬取数据,模拟普通用户的行为
- 基于动态页面的反爬虫:跟踪服务器发送的ajax请求,模拟ajax请求。
68、阅读下面的代码,它的输出结果是什么?
class Node(object):def __init__(self, sName):self._lChildren = []self.sName = sNamedef __repr__(self):"""显示属性:return:"""return "<Node '{}'>".format(self.sName)def append(self, *args, **kwargs):self._lChildren.append(*args, **kwargs)def print_all_1(self):"""深度优先:return:"""print(self)for oChild in self._lChildren:oChild.print_all_1()def print_all_2(self):"""广度优先:return:"""def gen(o):lAll = [o, ]while lAll:oNext = lAll.pop(0)lAll.extend(oNext._lChildren)yield oNextfor oNode in gen(self):print(oNode)oRoot = Node("root") # self.sName = root
oChild1 = Node("child1") # self.sName = child1
oChild2 = Node("child2") # self.sName = child2
oChild3 = Node("child3") # self.sName = child3
oChild4 = Node("child4") # self.sName = child4
oChild5 = Node("child5") # self.sName = child5
oChild6 = Node("child6") # self.sName = child6
oChild7 = Node("child7") # self.sName = child7
oChild8 = Node("child8") # self.sName = child8
oChild9 = Node("child9") # self.sName = child9
oChild10 = Node("child10") # self.sName = child10oRoot.append(oChild1)
oRoot.append(oChild2)
oRoot.append(oChild3)
# oRoot的情况:sName = root, _lChildren = [child1,child2,child3]
oChild1.append(oChild4)
oChild1.append(oChild5)
# sName = child1 ,_lChildren = [child4,child5]
oChild2.append(oChild6)
# sName = child2, _lChildren = [child6]
oChild4.append(oChild7)
# sName = child4, _lChildren = [child7]
oChild3.append(oChild8)
oChild3.append(oChild9)
# sName = child3,_lChildren = [child8,child9]oChild6.append(oChild10)
# sName = child6 _lChildren = [child10]# 说明下面代码的输出结果
# oRoot sName = root
# _lChildren = [[sName=child1,child4&7,child5],[sName=2,child6&child10],[sName = 3,child8,child9]]
# oRoot.print_all_1()
oRoot.print_all_2()
可以画成这样的图来进行推算:
数据结构
69、红黑树
红黑树与AVL的比较:
AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同的情况,旋转的次数比红黑树更多;
红黑是用于非严格的平衡来换取增删节点时候旋转次数的降低
所以简单说,如果你的应用中,搜索的次数远远大于插入和删除,那么选择AVL,如果搜索,插入删除次数几乎啥不多,应该选择RB。
70、台阶问题/斐波那契
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级别的台阶总过有多少种方法。
fib = lambda n:n if n<=2 else fib(n-1)+fib(n-2)
第二种方法:
def memo(func):cache = {}def wrap(*args):if args not in cache:cache[args] = func(*args)return cache[args]return wrap@memo
def fib(i):if i < 2:return 1return fib(i - 1) + fib(i - 2)print(fib(2))
第三种方法:
def fib(n):a, b = 0, 1for _ in range(n):a, b = b, a + breturn bprint(fib(4))
71、变态台阶问题
一只青蛙一次可以跳上1级台阶,也可以跳上2级……,它也可以跳上n级。求该青蛙跳上一个n级的台阶总过有多少种跳法
fib = lambda n: n if n < 2 else 2 * fib(n - 1)
72、矩形覆盖
我们可以用2*1的小矩形横着或者竖着取覆盖最大的矩形,请问用n个2*1的小矩形无重叠覆盖一个2*n的大巨星,总共有多少种方法?
第2*n个矩形的覆盖方法等于第2*(n-1)加上第2*(n-2)的方法。
f = lambda n: 1 if n < 2 else f(n - 1) + f(n - 2)
73、杨氏矩阵查找
在一个m行n列二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
74、去除列表中的重复元素
用集合
list(set(L))
用字典
Python 字典 fromkeys() 函数用于创建一个新字典,以序列 seq 中元素做字典的键,value 为字典所有键对应的初始值。
l1 = ['b', 'c', 'd', 'b', 'c', 'a', 'a']
l2 = {}.fromkeys(l1).keys()print(l2, {}.fromkeys(l1))
# 输出结果
# dict_keys(['b', 'c', 'd', 'a']) {'b': None, 'c': None, 'd': None, 'a': None}
用字典并保持顺序
l1 = ['b','c','d','b','c','a','a']
l2 = list(set(l1))
l2.sort(key=l1.index)
print (l2)
先排序然后删除
l1 = ['b','c','d','b','c','a','a']
l2 = []
[l2.append(i) for i in l1 if i not in l2]
print(l2)
75、创建字典的方法
# 直接创建dict1 = {'name': 'earth', 'port': '80'}# 工厂方法
items = [('name', 'earth'), ('port', '80')]
dict2 = dict(items)
dict3 = dict((['name', 'earth'], ['port', '80']))
print(dict3)
# fromkeysdict5={}.fromkeys(('x','y'),-1)
dict ={'x':-1,'y':-1}
dict4={}.fromkeys(('x','y'))
# dict4={'x':None, 'y':None}
print(dict5,dict4)# 输出结果
{'name': 'earth', 'port': '80'}
{'x': -1, 'y': -1} {'x': None, 'y': None}
Django
76、简单说一下Django的ORM的开发?
<1> all(): 查询所有结果 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象。获取不到返回None<3> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个。如果符合筛选条件的对象超过一个或者没有都会抛出错误。<4> exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象<5> order_by(*field): 对查询结果排序<6> reverse(): 对查询结果反向排序 <8> count(): 返回数据库中匹配查询(QuerySet)的对象数量。 <9> first(): 返回第一条记录 <10> last(): 返回最后一条记录 <11> exists(): 如果QuerySet包含数据,就返回True,否则返回False<12> values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系 model的实例化对象,而是一个可迭代的字典序列<13> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列<14> distinct(): 从返回结果中剔除重复纪录
77、简要说一下Restful框架
78、简要说一下你的Django是怎么在服务器上部署的
79、你是如何做到前后端分离的?什么是耦合开发?什么是非耦合开发?
80、django如何实现跨域名访问请求?
81、你平常做Web的时候,都用过Models的什么方法?
82、django的优点和缺点有哪些?
优点:
- 功能完善、要素齐全:自带大量企业Web开发常用工具和框架(比如分页、auth、权限管理),适合快速开发企业级网站。
- 完善的文档:经过十多年的发展和完善,Django有广泛的实践案例和完善的在线文档。开发者遇到问题时可以搜索在线文档寻求解决方案。
- 强大的数据库访问组件:Django的Model层自带数据库的ORM组件,使得开发者无须学习SQL语言即可对数据库进行操作。
- DJango先进的APP设计理念:APP是可插拔的,是不可多得的意思。不需要啦,可以直接删除,对系统整体影响不大。
- 自带台管理系统admin:只需要通过简单的几行配置和代码就可以实现一个完整的后台数据管理控制平台。
缺点:
- 大包大揽:对于一些轻量级应用不需要的功能模块Django也包括啦,不如Flask轻便。
- 过度封装:很多类和方法都封装类,直接使用比较简单,但改动起来就比较困难。
- 性能劣势:与c,c++性能上相比,Django性能偏低,当然这是Pyrhon的锅,其他Python框架在流量上来后会有同样的问题。
- 模版功能:django的模板实现类代码和样式完全分离,不允许模版里出现Python代码,灵活度对某些程序员来说可能不够。
83、说说看Django的请求生命周期
注意⚠️:最重要的是回答用户请求并不是一下子通过URL匹配就达到相应视图,返回数据也不是一下子就返回给用户,中间要经历层层中间件。详情请看自己整理的博客django中间件的学习
列举django中间件的5个方法?以及django中间件的应用场景
- .process_request:请求进来时,权限认证
- .process_view:路由匹配之后,能够得到视图函数
- .process_exception:异常时执执行
- .process_template_responseprocess:模板渲染时执行
- .process_response:请求有相应时执行
84、请列举几个django orm 中常用的获取数据查询集的方法
常用方法包括filter和exculde方法。字符串模糊匹配可以使用icontains,in等多种方法。
85、说说看django的Queryset有哪些特性
Django的QuerySet主要有两个特性:
- 惰性的。
- 自带缓存。
举个例子:下例中article_list视图从数据库查询一个标题含有django的全部文章列表:
article_list = Article.objects.filter(title__contains="django")
当我们定义article_list的时候,Django的数据接口QuerySet并没有对数据库进行任何查询。无论你加多少过滤条件,Django都不会对数据库进行查询。只有当你需要对article_list做进一步运算时(比如打印出查询结果,判断是否存在,统计查询结果长度),django才会真正执行对数据库的查询。这个过程被称为queryset的执行。
Django这样设计的本意是尽量减少对数据库的无效操作,比如查询了结果而不用是计算资源的很大浪费。
# example 1
for article in article_list:print(article.title
在例1中,当你遍历querset(article_list)时,所有匹配的记录会从数据库获取。这些结果会载入内存并保存在queryset内置的cache中。这样如果你再次便利或读取这个article_list时,Django就不需要再重复查询了,这样也可以减少对数据库的查询。
# Example 2: Good
article_list = Article.objects.filter(title__contains="django")
for article in article_list:print(article.title)# Example 3: Bad
for article in Article.objects.filter(title__contains="django"):print(article.title)# Example 4: Good——————if会导致article_list的执行article_list = Article.objects.filter(title__contains="django")
if article_list:for article in article_list:print(article.title)
else:print("No records")
如果不需要执行article_list,可以使用exists()方法,他只会检查查询结果是否存在 ,返回True或False,而不会缓存article_list。
# Example 5: Good
article_list = Article.objects.filter(title__contains="django")
if article_list.exists():print("Records found.")
else:print("No records")
统计查询结果数量优选count方法。
len()和count()均能统计查询结果的数量。一般来说count会更快,因为它是从数据库层面直接获取查询结果的数量,而不是返回整个数据集,而len会导致queryset的执行,需要将整个queryset载入内存后才能统计其长度。
# Example 6: Good
count = Article.objects.filter(title__contains="django").count()# Example 7:Bad
count = Article.objects.filter(title__contains="django").len()# Example 8: Good
article_list = Article.objects.filter(title__contains="django")
if article_list:print("{} records found.".format(article_list.len()))
当queryset非常大时,数据按需去取
当查询到的queryset的非常大时,会大量占用内存。我们可以使用values和value_list方法按需提取数据。
# Example 9: Good
article_list = Article.objects.filter(title__contains="django").values('title')
if article_list:print(article.title)article_list = Article.objects.filter(title__contains="django").values_list('id', 'title')
if article_list:print(article.title)
更新数据库部分字段请用update方法(还会返回更新条目的数目)
如果需要对数据库中的某条已有数据或某些字短进行更新,更好的方式是用update,而不是用save方法。
例10中需要把整个Article对象的数据先提取出来,缓存到内存中,变更信息后再写入数据库。
而例11直接对标题进行了更新,不需要把整个文章对象的数据载入内存,显然更高效。
# Example 10: Bad
article = Article.objects.get(id=10)
Article.title = "Django"
article.save()# Example 11: Good
Article.objects.filter(id=10).update(title='Django')
专业地使用explain方法
可以统计一个查询所消耗的执行时间,可以帮助程序员更好滴优化查询结果。
print(Blog.objects.filter(title='My Blog').explain(verbose=True))# output
Seq Scan on public.blog (cost=0.00..35.50 rows=10 width=12) (actual time=0.004..0.004 rows=10 loops=1)Output: id, titleFilter: (blog.title = 'My Blog'::bpchar)
Planning time: 0.064 ms
Execution time: 0.058 ms
86、什么是基于函数的视图(FBV)和基于类的视图(CBV)以及各自的缺点
FBV就是在视图里使用函数处理请求。CBV就是在视图里使用类处理请求。CBV的优点主要下面两种:
- 提高了代码的复用性,可以使用面向对象的技术,比如Mixin
- 可以用不同的函数针对不同的HTTO方法处理,而不是通过很多if来判断,提高代码可读性。
87、如何给基于类的视图CBV使用装饰器
需要借助django.utils模块的method_decorator来实现,它还支持decorators列表,如下所示:
from django.utils.decorators import method_decoratordecorators = [login_required, check_user_permission]@method_decorator(decorators, name='dispatch')
class ArticleCreateView(CreateView):model = Articleform_class = ArticleFormtemplate_name = 'blog/article_manage_form.html'# 1、给方法加:
@method_decorator(check_login)
def post(self, request):# 2、给dispatch加:
@method_decorator(check_login)
def dispatch(self, request, *args, **kwargs):
关于django的装饰器的操作
88、你能列举几个减少数据库查询次数的方法吗?
- 利用django queryset的惰性和自带缓存的特性
- 利用select_related和prefetch_related方法在数据库里面进行join操作
- 使用缓存
89、Django的模型继承有哪几种方法?它们有什么区别以及何时使用它们?
- 抽象模型继承
- 多表模型继承
- 代理模型
区别如下:
- django不会为抽象模型在数据库中生成自己的数据表。父类Meta中的abstract = True也不会传递给子类。如果你发现多模型有很多共同字段时,需使用抽象模型继承。
- 多表模型继承与抽象模型继承最大的区别在于Django也会为父类模型建立自己的数据表,同时隐式地在父类和子类之间简历一个一对一关系
- 如果我们只想改变某个模型的行为方法。而不是添加额外的字短或创建额外的数据表,我们就可以使用代理模型。设置一个代理模型,需要在子类模型过Meta选项中设置proxy=True,Django不会为代理模型生成新的数据表。
90、说说看如何自定义模版标签和过滤器?
首先你要在你的App目录下新建一个templatetags的文件见(不能取别的名字),里面必须伯包含__init__.py的空文件。在该目录下还有新建一个python文件专门存放你自定义的模板标签函数,例如:
blog/__init__.pymodels.pytemplatetags/__init__.pyblog_extras.pyviews.py
在模版中使用自定义的模板标签时,需要先使用{% load blog_extras %}载入自定义的过滤器,然后通过{% tag_name %} 使用它。
举例
我们将定义3个简单模板标签,一个返回string, 一个给模板context传递变量,一个显示渲染过的模板。我们在blog_extra.py里添加下面代码。
#blog_extra.py
from django import template
import datetime
from blog.models import Articleregister = template.Library()# use simple tag to show string
@register.simple_tag
def total_articles():return Article.objects.filter(status='p').count()# use simple tag to set context variable
@register.simple_tag
def get_first_article():return Article.objects.filter(status='p').order_by('-pub_date')[0]# show rendered template
@register.inclusion_tag('blog/latest_article_list.html')
def show_latest_articles(count=5):latest_articles = Article.objects.filter(status='p').order_by('-pub_date')[:count]return {'latest_articles': latest_articles, }
91、列举django的内置组件?
- .admin 是对model中对应的数据表进行增删改查提供的组件
- .model组件。 负责操作数据库
- .form组件:1、生成HTML代码。2、数据有效性校验。3、校验信息返回并展示
- .ModelForm组件:即用于数据库操作,也可用于用户请求的验证。
92、django的request对象是在什么时候创建的?
class WSGIHandler(base.BaseHandler):request = self.request_class(environ)
请求走到WSGIHandler类的时候,执行cell方法,将environ封装成request。
93、select_related和prefetch_related的区别?
前提:有外键存在时,可以很好的减少数据请求的次数,提高性能。
- select_related通过多表join关联查询,一次性获得所有数据,只执行一次SQL查询
- prefetch_related 分别查询每个表,然后根据它们之间的关系来进行处理,执行2次查询。
94、列举django ORM中三种能写SQL语句的方法
1.使用execute执行自定义的SQL直接执行SQL语句(类似于pymysql的用法)# 更高灵活度的方式执行原生SQL语句from django.db import connectioncursor = connection.cursor()cursor.execute("SELECT DATE_FORMAT(create_time, '%Y-%m') FROM blog_article;")ret = cursor.fetchall()print(ret)
2.使用extra方法 :queryset.extra(select={"key": "原生的SQL语句"})
3.使用raw方法1.执行原始sql并返回模型2.依赖model多用于查询
95、cookie和session的区别
- cookie:cookie是保存在浏览器端的键值对,可以用来做用户认证
- session:将用户的会话信息保存在服务端,key值是随机产生的字符串,value值是session的内容,依赖于cookie将每个用户的随机字符串保存到用户浏览器上
- Django中session默认保存在数据库中:django_session表
- flask,session 默认将加密的数据写在用户的cookie中。
96、如何使用django orm 批量创建数据?
objs = [models.Book(title="图书馆{}".format(i+15)) for I in range(100)]\
models.Book.objects.bulk_create(objs)
97、django的Form组件中,如果字段中包含choices参数,请使用两种方式实现数据源实时更新:
- 1.重写构造函数
def__init__(self, *args, **kwargs):super().__init__(*args, **kwargs)self.fields["city"].widget.choices = models.City.objects.all().values_list("id", "name")
- 2.利用ModelChoiceField字段,参数为queryset对象
authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())//多选
98、django的Model中的ForeginKey字段中的on_delete参数有什么作用
- 删除关联表中的数据时,当前表与其关联的field的操作
- django 2.0之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常。
99、Django的自模板中自定义filter和simple_tag的区别
- 自定义filter:{{参数1 |filter函数名:参数2}}
- 可以与if标签来使用
- 自定义时需要写两个形参
例子:自定义filter1. 在app01下创建一个叫templatetags的Python包2. 在templatetags的文件夹下创建py文件 myfilters3. 在py文件中写代码from django import templateregister = template.Library()@register.filterdef add_sb(value,arg='aaa'):return "{}_sb_{}".formart(value,arg)@register.filter(name='sb')def add_sb(value,arg='aaa'):return "{}_sb_{}".formart(value,arg) 4. 使用自定义filter{% load myfilters %}{{ name|add_sb:'xxx'}}{{ name|sb:'xxx'}}
- simple_tag:{% simple_tag函数名 参数1 参数2 %}
- 可以传多个参数,没有限制
- 不能与if标签来使用
例子:自定义simpletag创建1 、在app01中创建一个名字是templatetags的包,2、在包中创建一个py文件3、在py文件中导入from django import templateregister = template.Library()4、写函数@register.simple_tag(name="plus")def plus(a,b,c):return '{}+{}+{}'.format(a,b,c)5、加装饰器@register.simple_tag(name="plus")使用1、导入{% load mytag %}2、使用{% plus 1 2 3 %}
100、django中的csrf的实现机制
- 第一步:django第一次相应来自某个客户端的请求时,后端随机产生一个token值,把这个token保存在SESSION状态中;同时,后端吧这个token放到cookie中交给前端页面。
- 第二步:下次前端需要发起请求(比如发帖)的时候把这个token值加入到请求数据或者头信息中,一起传给后端;Cookies:{csrftoken:XXX}
- 第三步:后端校验前端请求带过来的token和session里的token是否一致。
101、基于django使用ajax发送post请求时,都可以使用哪种方法携带csrf_token?
- 后端将csrftoken传到前端,发送post请求时携带这个值发送
data: {csrfmiddlewaretoken: '{{ csrf_token }}'},
- 获取form中隐藏标签的csrftoken值,加入到请求数据中传给后端
data: {csrfmiddlewaretoken:$('[name="csrfmiddlewaretoken"]').val()},
- cookie中存在csrftoken,将csrftoken值放到请求头中。
headers:{ "X-CSRFtoken":$.cookie("csrftoken")}
102、django本身携带了runserver,为什么不能用来部署?(runserver和uWSGI的区别)
- runserver方法是调试Django时经常用到的运行方式,它使用django自带的WSGI Server运行,主要在测试和开发中使用,并且runserver开启的方式也是单进程的。
- uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。注意uwsgi是一个通信协议,而uWSGI是实现uwsgi协议和WSGI协议的WEB服务器。uWSGI具有超快的性能、第内存占用和多app管理等优点,并且搭配着Nginx就是一个生产环境了,能够将用户访问请求与应用 app 隔离开,实现真正的部署 。相比来讲,支持的并发量更高,方便管理多进程,发挥多核的优势,提升性能。
103、分别从前端、后端、数据库阐述Web项目的性能优化
前端优化:
- 减少http请求、例如制作精灵图
- html和css放在页面上部,JavaScript放在页面下面,因为js加载比HTML和CSS加载慢,所以要优先加载html和css,以防页面显示不全,性能差,也影响用户体验。
后端优化:
- 缓存存储都写次数高,变化少的数据,比如网站首页的信息、商品的信息等。应用程序读取数据时,一般是先从缓存中读取,如果读取不到或数据已失效,再访问磁盘数据库,并将数据再次写入缓存。
- 异步方式,如果有耗时操作,可以采用异步,比如celery
- 代码优化,避免循环和判断次数太多,如果多个if else判断,优先判断最有可能发生的情况。
数据库优化
- 如有条件,数据存放于redis,读取速度快
- 简历索引、外键等。
感谢以下网站
Python面试的100多题之61-90(详细版)相关推荐
- 《剑指offer—面试篇》-python面试经典100题(上)
- 假期怎么提升Python技能?100+编程题给你练~
我一开始很喜欢python的哲学,然后买了一个<python学习手册>,简单的了解了一下python 不过因为没什么实际的需求,只是了解,后来自己做网站用了Django,然后又做了一个网站 ...
- 假期怎么提升 Python 技能?100+ 编程题给你练~(附答案)
整理 | Jane 出品 | Python大本营 春节马上就要到了,怎么能让自己在假期里不掉队?今天,营长给大家准备一个项目: 100+ 编程练习,这些题如果能坚持每天至少完成一道,一定可以帮大家轻松 ...
- Python面试常用二十题总结
1.请至少用一种方法下面字符串的反转? 1).A[::-1] 2).交换前后字母的位置 t = list(A) l = len(t) for i, j inzip(range(l - 1, 0, -1 ...
- python数据结构与算法刷题——剑指offer第二版加部分leetcode题
说不清楚,只能看代码理解的用红色标出 查找算法:查找较排序来说较简单,不外乎顺序查找和二分查找.哈希表查找和二叉排序树查找.(很多面试官喜欢让应聘者写出二分查找(如test53)的代码)[注意:二分查 ...
- 数字IC设计工程师笔试面试经典100题-有答案
转自知乎答主ictown_数字IC设计工程师笔试面试经典100题-有答案-陈恩 1:什么是同步逻辑和异步逻辑?(汉王) 同步逻辑是时钟之间有固定的因果关系.异步逻辑是各时钟之间没有固定的因果关系. 同 ...
- python面试实战题(一)
python面试操作题整理 会不定期更新 循环报数3的出圈 按照年龄判断未成年还成年(条件语句)n多种方法 会不定期更新 循环报数3的出圈 题目: 100个人围一圈编号1-100,依次开始报数, 从1 ...
- 有没有可以刷python题的软件_你想要的Python面试都在这里了【315+道题】
第一部分 Python基础篇(80题) 1.为什么学习Python? 1.python是脚本语言,作为程序员至少应该掌握一本通用脚本语言,因为脚本语言与编译语言的开发测试过程不同,可以极大的提高编程效 ...
- 【python】python基础测试100题
python基础面试测试100题 Q1.什么是Python? Q2.Python的主要功能是什么? Q3.Python中支持的数据类型有哪些? Q4.列表和元组有什么区别? Q5.什么是Python模 ...
最新文章
- 解决Tomact启动时问题 Port 8080 required by Tomcat v8.0 Server at localhost is already in use.
- 【Network Security!】IP地址详解(看不懂你来打我)
- python编程300例_经典编程100例——python版(例75)
- How should I set up tag files for a multi-level directory hierarchy? kiss snow
- python3spark文本分类_如何用Spark深度集成Tensorflow实现文本分类?
- arcgis几何修复有作用吗_ArcGis拓扑的那些事儿(拓扑应用过程二)
- vue 带全选和多选的表格怎么写_vue+element-ui里面table组件多选框实现批量操作
- 如何击败腾讯_要击败这个新的电子游戏,请对其重新编程
- Oracle10g安装了11g的ODAC后,PL/SQL连接提示TNS:无法解析指定的连接标识符
- 基于stm32单片机外文文献_(强烈推荐)基于stm32的温度控制毕业论文设计
- 航空模型手工制作_小学生简易航空模型的制作
- 学生专用计算机怎么没声音,班班通电脑没声音了
- 空城计课件软件测试,空城计课件公开课.ppt
- 大学生英语跨文化交际阅读课程 Unit6 Text A
- 你一定要知道的,8大花店运营指南
- fri信号重构-sinc核滤波
- uniapp 日期计算年龄
- IT运维的相关需求分析报告(第一篇)
- 第九讲:Python爬取网页图片并保存到本地
- tiny4412编译出来的zImage不能开机
热门文章
- 华为推出Track AI以帮助检测世界各地儿童视力障碍的早期迹象
- FLASK点击按钮实现中英文切换
- 顺序表的操作例题——已知一个顺序表L, 其中的元素递增有序排列,设计一个算法,插入一个元素x (x为int 后保持该顺序表仍然递增有序排列(假设插入操作总能成功)。
- 二分查找:思路很简单,细节是魔鬼
- Turtlebot1入门教程-安装Turtlebot(Ubuntu18.04+Melodic)
- 采访吴岳师兄有感 by 王宇飞
- 听说朋友圈是爬虫爬不到的地方?开玩笑什么玩笑?可见可爬!
- Java获取拼音首字符
- Java递归算法——猴子吃桃
- Android 获取双卡手机IMEI,IMSI,ICCID