个人python开发数据分析面试题分享

1、Post和Get请求的区别?

答:GET 请求,请求的数据会附加在 URL 之后,以?分割 URL 和传输数据,多个参数用&连接。POST 请求:会把请求的数据放置在 HTTP 请求包的包体中。因此,GET 请求的数据会暴露在地址栏中,而 POST 请求则不会,所以:POST 的安全性比 GET 的安全性高。

在 HTTP 规范中,没有对 URL 的长度和传输的数据大小进行限制。但在实际开发过程中,对于Get,特定的浏览器对URL的长度有限制,因此在使用Get请求时,传输数据会受到URL的限制。对于 POST,由于不是 URL 传值,理论上是不会受限制的,但是实际上各个服务器会规定对 POST提交数据大小进行限制。

2、进程、线程、协程?

答:进程:一个运行的程序(代码)就是一个进程,没有运行的代码叫程序,进程是系统资源分配的最小单位,进程拥有自己独立的内存空间,所以进程间数据不共享,内存开销大。

线程:调度执行的最小单位,也叫执行路径,不能独立存在,依赖进程,存在一个进程至少有一个线程,叫主线程,而多个线程共享内存(数据共享,共享全局变量),从而极大地提高了程序的运行效率。

协程:是一种用户态的轻量级线程,协程的调度完全由用户自己控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

3、MySQL、redis、mongodb数据库的区别?

答:首先:MySQL是关系型数据库,redis和mongodb是非关系型数据库, 采用结构型数据存储

1.作用上,mysql用于持久化的存储数据到硬盘上,功能强大,但是速度慢;而redis用于存贮使用较为频繁操作的数据到缓存中,读取速度快;mongodb能够保证用户的访问速度和文档结构的存储方式,高效存储二进制大对象(比如照片和视频),然后支持复制集、主备、互为主备、自动分片等特性

2.MongoDB 建议集群部署, 更多的考虑到集群方案, Redis 更偏重与进程顺序写入, 虽然支持集群, 但也仅限于主-从模式。

3.需求上应用不同,MySQL和redis两者一般是配合使用。

4、range 和 xrange 的区别?

答: 两者用法相同,不同的是 range 返回的结果是一个列range对象,而 xrange 的结果是一个生成器,前者是直接开辟一块内存空间来保存列表,后者是边循环边使用,只有使用时才会开辟内存空间,所以当列表很长时,使用 xrange 性能要比 range 好。

5、http和https的区别?

答:HTTP 和 HTTPS 的区别主要如下:

1.http是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加密传输协议。

2.http和https 使用不同的连接方式,用的端口也不一样,前者是 80,后者是443。

3.http 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 http 协议安全。

6、Xpath和beautifulsoup有什么区别?

答:BeautifulSoup是一个库,而XPath是一种技术,python中最常用的XPath库是lxml。
	1.BeautifulSoup和lxml的原理不一样,BeautifulSoup是基于DOM的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多。而lxml只会局部遍历,另外lxml是用c写的,而BeautifulSoup是用python写的。
	2.BeautifulSoup用起来比较简单,API非常人性化,支持css选择器。lxml的XPath写起来麻烦,开发效率不如BeautifulSoup。
	3.总结起来就是需求比较确定,要求性能的场合用Xpath,快速开发用BeautifulSoup

7、链表的组成结构?

答:链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

8、爬虫里面的数据怎么去重?

答:nutch 去重。nutch 中 digest 是对采集的每一个网页内容的 32 位哈希值,如果两个网页内容完全一样,它们的 digest 值肯定会一样。

数据量不大时,可以直接放在内存里面进行去重,python 可以使用 set()进行去重。当去重数据需要持久化时可以使用 redis 的 set 数据结构。

当数据量再大一点时,可以用不同的加密算法先将长字符串进行压缩,再使用上面两种方法去重。

当数据量达到亿(甚至十亿、百亿)数量级时,内存有限,必须用“位”来去重,才能够满足需求。Bloomfilter 就是将去重对象映射到几个内存“位”,通过几个位的 0/1 值来判断一个对象是否已经存在。然而 Bloomfilter 运行在一台机器的内存上,不方便持久化(机器 down 掉就什么都没啦),也不方便分布式爬虫的统一去重。如果可以在 Redis 上申请内存进行 Bloomfilter,以上两个问题就都能解决了。

simhash 将一个文档转换成一个 64 位的字节,暂且称之为特征字,然后只需要判断他们的特征字的距离是不是

9、数据库中索引的原理及作用?

答:数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B_TREE。B_TREE索引加速了数据访问,因为存储引擎不会再去扫描整张表得到需要的数据;相反,它从根节点开始,根节点保存了子节点的指针,存储引擎会根据指针快速寻找数据。

10、redis数据库?用作什么?怎么实现hash这种存储方式?

答:redis是一个开源的内存数据结构数据库,用作数据库缓存和消息代理。它支持数据结构,如字符串、哈希、列表、集合、带范围查询的排序集合,具有:读写性能优异;支持数据库持久化(AOF:以日志的形式记录服务器所处理的每一个写、删除操作;RDB:在指定的时间间隔内将内存中的数据集快照写入磁盘);数据结构丰富等优点。Redis中的hash类型可以看成具有字典key和value的容器,其键值对存储方式通过字典保存,然后通过哈希表的节点保存字典中的键值对。

11、装饰器及其应用场景?迭代器?生成器?两者的区别?

答:装饰器的实现是由闭包支撑的,其本质上是⼀个python函数,它可以在让其他函数在不需要做任何代码变动的前提下增加额外的功能;经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、缓存、事务处理等。装饰器是解决这类问题的绝佳设计。

迭代器是一种概念上的抽象对象,他能够用来遍历标准模板库容器中的部分或全部元素,每个迭代对象代表容器中的确定地址。

生成器是创建迭代器的简单而强大的工具,只是在需要返回数据的时候使用yield语句,每次next()被调用时,生成器会返回它脱离的位置。

区别:生成器能做到迭代器能做的所有事,而且因为自动创建了 iter()和 next()方法,生成
器显得特别简洁高效,使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序状态的自动方法,当生成器终结时,还会自动抛出 StopIteration 异常。

12、管道通信?

答:管道通信(Communication Pipeline)即发送进程以字符流形式将大量数据送入管道,接收进程可从管道接收数据,二者利用管道进行通信。主要有:普通管道(有单工和血缘关系的限制);流管道(实现了双向传输,但有血缘关系的限制);命名管道(既可双向传输又实现了无血缘关系进程间的通信)。无论是SQL Server用户,还是PB用户,作为C/S结构开发环境,他们在网络通信的实现上,都有命名管道的方法。命名管道的灵活性表现在: 既可用于本地,又可用于网络;可以通过它的名称而被引用;支持多客户机连接;支持双向通信;支持异步重叠I/O操作。

13、Socket?

答:套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。一般的网络提供了流式套接字,数据报套接字和原始套接字三种不同类型的套接字。

14、python的数据结构?

答:字典(dict):字典是一组键和值,通过键进行查找,没有顺序,使用{}表示;

字符串(str):字符串是python中最常用的数据类型;

列表(list):列表是python中最使用最频繁的数据类型,在其他语言中通常叫做数 组,通过索引查找,使用[]表示;列表的索引从0开始

元组(tuple):元组将多样的对象集合到一起,不能修改,通过索引进行查找使用()表示。

15、排查和优化SQL语句方法有哪些?

答:一般SQL效率低的原因有服务器内存不够,sql分配的内存不够,sql语句设计不合理,没有相应的索引或索引不合理,表数据过大或者数据冗余。

排查:查看执行时间和cpu占用时间;查看查询对I/O的操作情况;查看执行计划。

优化SQL的方法:
1.保证不查询多余的列与行:
	尽量避免select * 的存在,使用具体的列代替*,避免多余的列
	使用where限定具体要查询的数据,避免多余的行
	使用top,distinct关键字减少多余重复的行
	多使用索引进行查询
2.慎用distinct关键字:
	distinct在查询一个字段或者很少字段的情况下使用,会避免重复数据的出现,给查询带来优化效果。但是查询字段很多的情况下使用,则会大大降低查询效率。
3.慎用union关键字:
	此关键字主要功能是把各个查询语句的结果集合并到一个结果集中返回给你。
4.连接查询的优化:
	尽量不使用主外键来进行连表
	内连接结果集大小取决于左右表满足条件的数量
	左连接取决与左表大小,右相反。

16、python常用模块儿?

答:sys模块:与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境。

os模块:对操作系统进行操作。

Time模块:提供日期、时间功能的类和函数。

Hashlib模块:提供字符加密功能。

random模块:一般用于生成随机数。

Numpy模块、pandas模块科学计算库,用于数据分析。

17、列举数据挖掘算法?

答:k-means:K均值;SVM:支持向量机;EM:期望最大值算法;KNN:最近邻算法;NB:朴素贝叶斯;AR:自回归模型。

18、常用的聚类算法,并详细说明其中一种原理?

答:K-means(K均值);KNN(最近邻算法);EM(期望最大值算法)

K-means:(1)首先我们选择一些类/组,并随机初始化它们各自的中心点。

(2) 计算每个数据点到中心点的距离,数据点距离哪个中心点最近就划分到哪一类。

(3) 计算每一类中中心点作为新的中心点。

(4) 重复以上步骤,直到每一类中心在每次迭代后变化不大为止。也可以多次随机初始化中心点,然后选择运行结果最好的一个。

19、python中django怎么和数据库同步?

答:python manage.py makemigrations
 	python manage.py migrate

20、python中的中间件有什么功能?

答:中间件是一个用来处理请求和响应的框架级别钩子,它是一个轻量,低级别的插件系统,用于全局范围内改变Django的输入,输出。每个中间件组件都负责做一些特定的功能。简单的来说,中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作,它本质上就是一个自定义类,类中定义了几个方法,Django框架会在请求的特定的时间去执行这些方法。

21、原生mysql中的去重关键字是什么?

答:distinct;它可以从 select语句的结果中消除重复的行。如果没有指定 distinct,将返回所有行,包括重复的行。

22、事务?

答:事务是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。这些操作要么都做,要么都不做,是一个不可分割的工作单位。通过事务,SQL Server能将逻辑相关的一组操作绑定在一起,以便服务器保持数据的完整性,一个事务可以是一条SQL语句,一组SQL语句或整个程序。

原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。

一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

隔离性(isolation):一个事务的执行不能被其他事务干扰。

持久性(durability):一个事务一旦提交,对数据库中数据的改变就应该是永久性的。

23、Session与cookie有什么区别?

答:cookie:客户端会话机制,session:服务器端会话机制

1.cookie 数据存放在客户的浏览器上,session 数据放在服务器上。

2.cookie 不是很安全,别人可以分析存放在本地的 cookie 并进行 cookie 欺骗,考虑到安全应用 session。

3.session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。

4.单个cookie保存的数据不能超过 4K,大多浏览器限制一个站点最多保存 20 个cookie。

24、Mysql的常见引擎有哪些?区别是什么?为什么myisam比innodb查询速度快?

答:常见引擎有InnoDB、myiasm、memory、merge。

1. InnoDB支持事务,Myisam不支持,对于InnoDB每一条SQL语言都默认封装成事务。
2. InnoDB支持外键,而Myisam不支持。
3. InnoDB和myisam都是聚集索引,都使用B+Tree作为索引结构,但innoDB数据文件是和(主键)索引绑在一起,myisam数据文件和索引是分离。
4. InnoDB不支持全文索引,Myisam支持全文索引,查询效率上Myisam要高;
5. InnoDB支持表、行(默认)级锁,而Myisam支持表级锁。

innoDB在做select的时候,要维护的东西比myisam多很多:
	1)innoDB需要缓存数据块,Myisam只缓存索引块;
	2)InnoDB寻址要映射到块,再到行,Myisam记录的直接是文件的地址,定位比innoDB要快
	3)innoDB还需要维护MVCC(多版本并发控制机制)一致

25、Mysql中char和var char主要不同之处是什么?

答:char的长度是不可变的,而varchar的长度是可变的,但char类型的效率比varchar的效率稍高
因为char无论存储数据长度本身长度多少,都会占用固定的长度,因此存储空间占用会有一定的浪费,而varchar由于是可变长度,但在性能上会受到一定的影响。对于长度变化不大,且要求查询速度的,使用char会更加合适,而varchar更节约存储空间。

26、HTTP方法有哪些?Delete方法是表单提交还是参数提交?

答:HTTP请求的常用方法有:GET方法、POST方法、HEAD方法、PUT方法、DELETE方法、CONNECT方法、OPTIONS方法、TRACE方法

27、URL的编码是用来干什么的?

答:url编码用来打包表单输入的格式,将URL中的非ASCII字符转换为可以为Web浏览器和服务器普遍接受的、有明确表示形式的格式,因为URL只能通过使用ASCII字符集(十六进制)将特殊字符在Web浏览器和服务器上显示。在URL编码中,非ASCII字符将会被替换为“%”,后跟十六进制数字的格式。

28、多个进程可以操作同一个内存吗?为什么?

答:可以,但是多个进程操作同一个内存,会造成内存里面的数据混乱,需要加一个锁来进行限制,但是互斥锁会使运行速度大大减慢,所以我们一般不这样做。

29、linux哪些信号不能被捕获,程序中用什么函数发送信号,命令行用什么命令发信号?

答:sigstop和sigkill不能被捕获或者忽略;
	程序中使用sigqueue函数发送信号,sigqueue的第一个参数是指定接收信号的进程ID,第二个参数确定即将发送的信号,第三个参数是一个联合数据结构union sigval,指定了信号传递的参数;
	命令行中使用kill命令发送信号,raise函数允许进程向自身发送信号,alarm函数设置了一个定时器,当定时器到了给当前进程发送SIGALRM信号。

30、select/epoll的优缺点?

答:select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,缺点在于单个进程能够监视的文件描述符数量存在最大限制,在Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。

epoll可以同时支持水平触发和边缘触发(只告诉进程哪些文件描述符刚刚变为就绪状态,如果没有采取行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。

31、Django model查询时如何对返回数据进行排序?

答:方法一:order_by函数:
例:Track.objects.all().order_by('-id'):id'表示升序,'-id'表示降序,是默认升序。.all()省略,默认查询所有。
Track.objects.all().order_by('-id','title'):也可以多个字段进行排序。
方法二:Meta选项ording
例:class Track(models.Model):
    album = models.ForeignKey(Album, related_name='tracks')
    order = models.IntegerField()
    title = models.CharField(max_length=100)
    class Meta:
        db_table = 'track'
        ordering = ('-id')
ordering它是一个字符串的列表或元组。每个字符串是一个字段名,前面带有可选的“-”前缀表示倒序。前面没有“-”的字段表示正序。使用"?"来表示随机排序。

32、Django Form中判断表单是否合法的方法是什么?如何自定义验证某个字段?

答:form.is_valid():验证表单数据是否合法

form.clean_data:获取表单数据

form.errors:表单的错误以字典形式返回

自定义验证某个字段可以利用Django的Form或者是ModelForm来解决。

33、深拷贝,浅拷贝?

答:深拷贝是将对象及值复制过来,两个对象修改其中任意一个的值另一个的值不会改变

浅拷贝只是复制对象的引用地址,两个对象指向同一个内存地址,改变其中任意一个都会改变另一个的值。

34、闭包的概念,一般用于什么地方?

答:在一个函数的内部定义另外一个函数,内部的函数调用外部变量的方法称为闭包
闭包常常应用于装饰器、继承和惰性求值(常应用在数据库访问)等方面。

35、staticmethod与classmethod的区别,那种场景下使用?使用静态方法和类方法的原因?

答:classmethod(fn)表明函数fn是类的函数而非类实例的函数,在语法上,它要求fn的函数签名至少要有1个参数,函数被调用时,解释器会将类作为第1个参数传给fn。

​ staticmethod(fn)表明函数fn是类的静态方法。如果该函数想声明成静态成员,则只需在其定义体前加上”@staticmethod”,利用装饰器语法糖来实现(cls.fun)的目的。采用静态方法可以简化和加速类属性的操作。

36、用python写一个简单的使用装饰器的例子?

答:def makeBold(fn):
    	def wrapped():
         	return '123' + fn() + '123'
    	return wrapped

   def makeItalic(fn):
   		def wrapped():
        	return '456' + fn() + '456'
   		return wrapped

  @makeBold
  def test1():
      return '  hello world   '

  @makeItalic
  def test2():
      return '  hello world  '

  @makeBold
  @makeItalic
  def test3():
      return '  hello world  '

  print(test1())
  print(test2())
  print(test3())
输出:
123  hello world   123
456  hello world  456
123456  hello world  456123

37、Mongodb中多条记录做更新操作的命令:?

答:update命令格式:

db.collection.update(criteria,objNew,upsert,multi)

参数说明:criteria:查询条件

objNew:update对象和一些更新操作符

upsert:如果不存在update的记录,是否插入objNew这个新的文档,true为插入,默认为false,不插入。

multi:默认是false,只更新找到的第一条记录。为true,把按条件查询出来的记录全部更新。

例:
db.classes.insert({"name":"c1","count":30})> db.classes.insert({"name":"c2","count":30})
db.classes.update({"count":{$gt:50}},{$set:{"name":"c5"}},true,false)

save命令格式:

db.collection.save(obj)

obj代表需要更新的对象,如果集合内部已经存在一个和obj相同的"_id"的记录,Mongodb会把obj对象替换集合内已存在的记录,如果不存在,则会插入obj对象。

38、用程序实现:从一个集合中找出两个元素a,b使得a+b=8.例如:集合{1,2,4,4},通过程序则找出a=4,b=4?

答:c = []
d = {1,0,2,3,6,8}
def add():
    for m in d:
        c.append(m)
    i = 0
    while i < len(c):
        a = c[i]
        j = 1
        while j <= i:
            b=c[j]
            if a + b == 8:
                print(a,b )
            j += 1
        i +=1
add()

39、Python2与Python3的区别,以及一些库的用法?

答:(1)Python3 对 Unicode 字符的原生支持:
Python2 中使用 ASCII 码作为默认编码方式导致 字符串有 str 和 unicode两种类型,Python3 只支持 unicode 的 string。

(2)Python3 采用的是绝对路径的方式进行 import,Python2 中相对路径的 import 会导致标准库导入变得困难。

(3)Python2 中存在老式类和新式类的区别,Python3 统一采用新式类。新式类声明要求继承 object,必须用新式类应用多重继承。

(4)Python3 使用更加严格的缩进,1个tab只能找另外一个tab替代。Python2 的缩进机制中,1个tab和 8个space是等价的。

40、数据库的增删改查基本命令?

答:增:insert

删:delete

改:update

查:select或show

虚拟机操作mysql数据库(延伸):

进入mysql 命令行:mysql -uroot -p;

查看所有数据库:show databases;

创建数据库:create database 数据库名 charset utf8;

删除数据库:drop database 数据库名;

选择数据库:use databases;

查看所有表:show tables;

查看创建数据库的语句:show create database databasename;

查看创建表的语句:show create table tablename;

查看表结构:desc tablenmae;

41、如何用后端手段解决用户重复提交表单的问题?

42、Python内存管理?

答:内存管理机制:引用计数、垃圾回收、内存池。

​ 引用计数:引用计数是一种非常高效的内存管理手段, 当一个 Python 对象被引用时其引用计数加 1, 当其不再被一个变量引用时则计数减 1. 当引用计数等于 0 时对象被删除。

​ 垃圾回收:(1)引用计数;(2)标记清除;(3)分代回收

​ 内存池:(1). Python 的内存机制呈现金字塔状,-1,-2 层主要由操作系统进行操作;

(2) 第 1 层和第 2 层是内存池,有 Python 的接口函数实现,当对象小于256K 时由该层直接分配内存;

(3) 第 3 层是最上层,也就是我们对 Python 对象的直接操作;

调优手段:手动垃圾回收;调高垃圾回收阀值;避免循环引用

43、不定长参数*args与**kwarges怎么传入参数?


44、开发调试工具ipython


45、脚本编程语言 grep awk sed


46、django里怎么查询一个表里的前十条数据?


47、python不用内置函数怎么去重?

答:1,用循环查找的方式
		li = [1,2,3,3,4,2,3,4,5,6,1]
        news_li = []
        for i in li:
            if i not in news_li:
                news_li.append(i)
        print (news_li)
    2,应用while循环遍历的方式
    	def quchong(n):
    		for x in n:
        		while n.count(x) > 1:
            	del n[n.index(x)]
    		return n
		li = [1,4,3,3,4,2,3,4,5,6,1]
		quchong(li)
	3,使用keys()方式
		li = [1,0,3,7,7,5]
		quchong = list({}.fromkeys(li).keys())
		print (quchong)

48、反向代理服务器有什么用?怎么配置?

答:反向代理是代理服务器的一种。服务器根据客户端的请求,从其关联的一组或多组后端服务器(如Web服务器)上获取资源,然后再将这些资源返回给客户端,客户端只会得知反向代理的IP地址,而不知道在代理服务器后面的服务器簇的存在。

49、WSGI,uwsgi,uWSGI的概念,用uWSGI有什么好处?

答:概念:WSGI:WSGI的全称是Web Server Gateway Interface(Web服务器网关接口);是一种描述web服务器(如nginx,uWSGI等服务器)如何与web应用程序(如用Django、Flask框架写的程序)通信的规范、协议。
   		uwsgi:与WSGI一样,是uWSGI服务器的独占通信协议,用于定义传输信息的类型。每一个uwsgi packet前4byte为传输信息类型的描述,与WSGI协议是两种东西,据说该协议是fcgi协议的10倍快。
   		uWSGI:uWSGI是一个全功能的HTTP服务器,实现了WSGI协议、uwsgi协议、http协议等。它要做的就是把HTTP协议转化成语言支持的网络协议。比如把HTTP协议转化成WSGI协议,让Python可以直接使用。
uWSGI的特点:超快的性能
		   低内存占用(实测为apache2的mod_wsgi的一半左右)
		   多app管理
		   详尽的日志功能(可以用来分析app性能和瓶颈)
		   高度可定制(内存大小限制,服务一定次数后重启等)



50、Flask框架,Django框架的区别及优缺点?

答:Flask:
1、轻量级web框架,只有一个内核,默认依赖jinja2模板和werkzeug WSGI工具集;
2、自由、灵活、可扩展性强,有强大的第三方库;
3、适用于做小型的网站以及web服务的API,开发大型网站,架构需要自行设计;
4、与关系型数据库结合不弱于Django,与非关系型数据库结合优于Django
Django:
1、重量级web框架,功能齐全,提供一站式解决思路;
2、自带ORM和模板引擎,但灵活和自由度不高;
3、自带数据库管理APP,开发文档丰富,完善;
4、成熟,稳定,开发效率高,相对于Flask,Django的整体封闭性好,适合做企业级开发。

51、设计模式有哪几种?设计一个单例模式?

答:python的设计模式大致有:桥接模式、观测模式、适配模式、工厂模式和单例模式
单例模式举例:
class Singleton(object):
    __instance = None

    def __new__(cls):
        #如果类属性__instance的值为None,
        #那么就创建一个对象,并且赋值为这个对象的引用,保证下次调用这个方法时
        #能够知道之前已经创建过对象了,这样就保证了只有1个对象
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance

a = Singleton()
b = Singleton()

print(id(a))
print(id(b))

a.age = 19 #给a指向的对象添加一个属性
print(b.age)#获取b指向的对象的age属性

53、Python的优缺点?

答:优点:
	免费、开源:这意味着源代码可以由更多人来维护;
	解释性语言:运行时不需要编译;
	开发效率非常高,拥有强大的第三方库,降低了开发周期;
	高层语言:编写时无需考虑如何管理程序和底层的细节;
	可移植性强:可以在多平台上开发,在多语言中嵌入,使代码具有脚本的功能;
	支持多线程,多进程和面向对象的编程。
缺点:
	使用独特的语法格式来区分语句关系;运行速度和c、c++相比,相对较慢。

54、数据库结构设计?

答:数据库设计是根据用户的需求,在某一具体的数据管理系统上,设计数据库的结构和建立数据库的过程,是建立数据库及应用系统的技术,是信息开发和建设的核心技术。
设计原则:一对一原则:通过利用此原则能够尽量减少维护问题的出现,保证数据维护工作顺利开展同时降低维护工作难度。
独特命名原则:能够减少数据冗杂,维护数据一致性,保持各关键词之间存在必然相对应联系。
双向使用原则:包括:事务使用原则和索引功能原则
重要性:有利于资源节约、软件运行速度和软件故障的减少。

55、什么是并行并发?有什么区别?以及解决办法?

答:并发,在操作系统中,是指一个时间段中有几个程序都处于启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。
	并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。

56、解释存储过程和触发器?

答:存储过程是将常用的或很复杂的工作,预先用SQL语句写好并用一个指定的名称存储起来, 如果要使用与已定义好的存储过程的功能相同的服务时,只需调用execute,即可自动完成命令。
	触发器是个特殊的存储过程,它的执行是由单个事件来触发,触发器经常用于加强数据的完整性约束和业务规则等。

57、Delete和Truncate Table语句的区别?

答:DELETE语句和TRUNCATE语句,都是删除数据表中的数据,但是它们对数据库的影响是不一样的。一般来讲DELETE用于日常数据表的删除操作,TRUNCATE则用于对数据库整体性的维护性操作。
	DELETE和TRUNCATE TABLE的最大区别是DELETE可以通过WHERE语句选择要删除的记录。但执行得速度较慢,可以返回被删除的记录数。而TRUNCATE TABLE删除表中所有的数据,并且不能返回被删除的记录,但执行速度非常快。
	总结就是:当你不再需要该表时,用 drop;当你仍要保留该表,但要删除所有记录时,用truncate;当你要删除部分记录时, 用 delete。

58、二叉树,广度遍历和深度遍历?

答:深度遍历二叉树是先访问根结点,然后遍历左子树,最后遍历右子树,因此我们可以利用堆栈的先进后出的特点,先将右子树压栈,再将左子树压栈,这样左子树就位于栈顶,可以保证结点的左子树先与右子树被遍历
	广度遍历又叫宽度优先搜索或横向优先搜索,是从根结点开始沿着树的宽度搜索遍历,可以利用队列实现广度优先搜索。

59、Django工作流程?

答:1.在启动Django服务器的同时就载入了在同一目录下的settings.py。该文件包含了项目中的配置信息,例如其中最重要的配置ROOT_URLCONF,它告诉Django哪个Python模块应该用作本站的URLConf,默认的是urls.py

2.当访问url的时候,Django会根据ROOT_URLCONF的设置来装载URLConf。

3.然后按顺序逐个匹配URLConf里的URLpatterns。如果找到则会调用相关联的视图函数,并把HttpRequest对象作为第一个参数(通常是request)

4.最后该视图函数负责返回一个HttpResponse对象。

60、快速排序的原理?

答:1、从数列中挑出一个元素,称为 “基准”(pivot);
	2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。
	3、递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

61、时间复杂度和空间复杂度?

	一个算法的优劣主要从算法的执行时间和所占用的存储空间两个方面衡量。
	时间复杂度是指算法执行语句的次数。当我们面前有多个算法时,我们可以通过计算时间复杂度,判断出哪一个算法在具体执行时花费时间最少
常见的时间复杂度有:
O(1)       :基于哈希表的查找算法
O(LOG2(N)) :二分查找、B树查找
O(N)       :单次循环、遍历
O(N*LOG2(N)):快速排序
O(N**2)     :冒泡排序
	空间复杂度是指一个算法在运行过程中临时占用存储空间的大小,记做S(n)=O(f(n))。比如直接插入排序的时间复杂度是O(n^2),空间复杂度是O(1) 。

62、什么是对称和非对称加密?举例子?

	对称加密算法在加密和解密时使用的是同一个秘钥
	非对称加密算法在使用时需要同时拥有公开密钥和私有密钥,公开密钥与私有密钥相对应,如果在对数据的加密过程中使用了公开密钥,那么只有使用相对应的私有密钥才能解密;反之,如果在对数据进行加密时使用了私有密钥,也只有使用与之相对应的公开密钥才能解密。
	对称加密例子:发电报

63、MVC与MVT是什么?区别?

答:MVC开始是存在于桌面程序中的,M是指业务模型(数据库)model,V是指用户界面(html) view,C则是控制器 controler,使用MVC的目的是将M和V实现代码分离,从而使同一个程序可以使用不同的表现形式。MVC实现了模型层的复用,核心思想就是高内聚,低耦合。
MVT也叫MTV,其本质上就是MVC的变种,M是指业务模型model,T是指模板-html,V是指视图函数,相当于MVC中的控制器。

64、TCP过程?

三次握手:
第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入syn_sent状态,等待服务器确认;
第二次握手:服务器接收到syn包,确认客户端的syn,同时返回一个syn给客户端,进入syn_sent状态;
第三次握手:客户端接收服务器的syn_ack包,并向服务器发送确认包,客户端与服务器进入连接状态,完成三次握手。
四次挥手:
第一次挥手:客户端进程发出连接释放报文,并停止发送数据;
第二次挥手:服务器收到连接释放报文,发出确认报文,服务器进入等待关闭状态;
第三次挥手:客户端接收服务器确认的请求后,客户端进入终止等待状态,等待服务器发送连接释放报文;
第四次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,客户端接收后发送确认,完成四次挥手,连接断开

65、Redis为什么是单进程单线程?

答:磁盘是分磁道、分簇存储数据的,所以数据往往不是连续排列在同一磁道上,在读取数据时往往需要在磁道之间反复移动,因此存在寻道耗时!另外,盘面旋转将请求数据所在扇区移至读写头下方还存在旋转耗时!这时线程在“阻塞”着等待磁盘,此时操作系统可以将那个空闲的CPU核心用于其他线程服务。因此在I/O操作的情况下,使用多进程多线程,效率会更高!
	Redis客户端执行一条命令分为四个过程:发送命令、命令排队、命令执行、返回结果,因为redis是将数据存储在内存中,所以不涉及I/O操作,所以设计为单线程是效率最高的!Redis的性能和CPU无关,他只与机器内存大小和网络带宽有关。
	使用单进程单线程好处:
1. 代码更清晰,处理逻辑更简单
2. 不用去考虑各种锁的问题,不存在加锁释放锁的操作,出现死锁导致性能消耗
3. 不存在多进程或者多线程的切换而消耗CPU

66、怎么实现负载均衡?

答:负载均衡就是指将负载进行平衡、分摊到多个操作单元上进行运行,例如FTP服务器、Web服务器等,从而协同完成工作任务。
	Nginx作为一种多功能服务器,不仅提供了反向代理隐藏主机ip的能力,还拥有简单的缓存加速功能。当然Nginx最强大的功能还是分发请求,不仅提供了哈希,一致性哈希,负载均衡等多种请求分发模式,还保证了自己服务的轻量和稳定。Nginx服务器常年工作在高并发请求的环境下,也极少宕机
	负载均衡的机制:轮询(默认方法);权重轮询;ip-hash等机制。

67、唯一索引与普通索引的区别?

答:唯一索引和普通索引使用的结构都是B-tree,执行时间复杂度都是O。
	唯一索引在能确定某个数据列只包含彼此各不相同的值时使用,唯一索引可以保证数据记录的唯一性。事实上,在许多场合,人们创建唯一索引的目的往往不是为了提高访问速度,而只是为了避免数据出现重复
    普通索引的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件或排序条件中的数据列创建索引。
	

68、查询集与懒查询

答:查询集的缓存:每个查询集都包含一个缓存,来最小化对数据的访问,在新建的查询集中,缓存首次为空,第一次对查询集求值,会发生数据缓存,django会将查询出来的数据做一个缓存,并返回查询结果,以后的查询直接使用查询集的缓存,而不会真正的查询数据库。
	懒查询:只有我们在迭代结果集或者获取单个对象属性的时候,他才会去查询数据。

69、三大范式

答:第一范式:数据库表的每一列都是不可分割的原子数据项。
	第二范式:建立在第一范式的基础上,要求数据库表中的每个实例或记录必须是可以唯一被区分的, 即唯一标识。
	第三范式:建立在第二范式的基础上,任何非主属性不依赖与其他非主属性,即引用主键。

70、堆和栈

答:堆(Heap)与栈(Stack)是开发人员必须面对的两个概念,在理解这两个概念时,需要放到具体的场景下,因为不同场景下,堆与栈代表不同的含义。一般情况下,有两层含义:
	1,程序内存布局场景下,堆与栈表示的是两种内存管理方式;
		(1):管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;
		(2):空间大小不同。栈的大小要远远小于堆的大小;
		(3):栈的生长方向向下,内存地址由高到低;堆的生长方向向上,内存地址由低到高;
		(4):分配方式的不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配;
		(5):分配效率不同。堆的效率比栈要低得多;
		(6):存放内容不同。栈存放基本类型的变量数据,局部变量,对象的引用;堆存放使用new创建的对象,全局变量。
	2,数据结构场景下,堆与栈表示两种常用的数据结构。
		 栈:就像装数据的桶或箱子,它是一种具有‘后进先出’性质的数据结构,也就是说后存放的先取,先存放的后取。
		 堆:像一棵倒过来的树,而堆就不同了,堆是一种经过排序的树形数据结构,每个结点都有一个值;通常我们所说的堆的数据结构,是指二叉堆。
		 队列:‘先进先出’,像栈一样,队列也是一种线性表。它允许在表的一端插入数据,在另一端删除元素。
	

71、MySQL主从复制原理及过程详细描述

(1)在Slave服务器上执行start slave 命令开启主从复制开关,主从复制开始进行
(2)此时,Slave服务器的I/O线程会通过在Master上已经授权的复制用户权限请求去连接Master服务器,并请求从指定的binlog日志文件的指定位置(日志文件名和位置就是在配置主从复制服务时执行change master命令指定的)之后开始发送binlog日志内容
(3)Master服务器接受来自Slave服务器的I/O线程的请求之后,其上负责复制的binlog dump线程会根据Slave服务器的I/O线程请求的信息,分批读取指定binlog日志文件所在位置之后的binlog日志信息,然后返回给Slave端的I/O线程。返回的信息中除了binlog日志内容之外,还包括在Master服务器端记录的新的binlog文件名称,以及在新的binlog中的下一个指定的更新位置
(4)当Slave服务器的I/O线程获取到Master服务器上I/O线程发送的日志内容及日志文件的位置点之后,会将binlog日志内容依次写入到Slave端自身的Relay Log(即中继日志)文件(MySQL-relay-bin.XXX)的最末端,并将新的Binlog文件名和位置记录到master-info文件中,以便于下一次读取Master端新的binlog日志时,能够告诉Master服务器需要从新的binlog日志的指定文件及位置开始请求新的binlog日志内容
(5)Slave服务器端的SQL线程会实时地检测本地Relay Log中I/O线程新增加的日志内容,然后及时地把Relay Log文件中的内容解析成Sql语句,并将自身Slave服务器上按照解析SQL语句的位置顺序执行和应用这些SQL语句,并将当前应用中继日志的文件名及位置点记录在relay-log.info中

72、多线程和多进程的区别?

多进程与多线程的区别 进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是处于运行状态下的操作系统本身;所有由你启动的进程都是用户进程。进程是操作系统进行资源分配的单位。在Windows下,进程又被细化为线程,也就是一个进程下有多个能独立运行的更小的单位。 在同一个时间里,同一个计算机系统中如果允许两个或两个以上的进程处于运行状态,这便是多任务。现代的操作系统几乎都是多任务操作系统,能够同时管理多个进程的运行。多任务带来的好处是明显的,比如你可以边听mp3边上网,与此同时甚至可以将下载的文档打印出来,而这些任务之间丝毫不会相互干扰。那么这里就涉及到并行的问题,俗话说,一心不能二用,这对计算机也一样,原则上一个CPU只能分配给一个进程,以便运行这个进程。我们通常使用的计算机中只有一个CPU,也就是说只有一颗心,要让它一心多用,同时运行多个进程,就必须使用并发技术。实现并发技术相当复杂,最容易理解的是“时间片轮转进程调度算法”,它的思想简单介绍如下:在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短(比如10毫秒),这样用户根本感觉不出来CPU是在轮流为多个进程服务,就好象所有的进程都在不间断地运行一样。但实际上在任何一个时间内有且仅有一个进程占有CPU。如果一台计算机有多个CPU,情况就不同了,如果进程数小于CPU数,则不同的进程可以分配给不同的CPU来运行,这样,多个进程就是真正同时运行的,这便是并行。但如果进程数大于CPU数,则仍然需要使用并发技术。在Windows中,进行CPU分配是以线程为单位的,一个进程可能由多个线程组成,这时情况更加复杂,但简单地说,有如下关系: 总线程数<= CPU数量:并行运行总线程数 > CPU数量:并发运行并行运行的效率显然高于并发运行,所以在多CPU的计算机中,多任务的效率比较高。但是,如果在多CPU计算机中只运行一个进程(线程),就不能发挥多CPU的优势。这里涉及到多任务操作系统的问题,多任务操作系统(如Windows)基本原理是:操作系统将CPU的时间片分配给多个线程,每个线程在操作系统指定的时间片内完成(注意,这里的多个线程是分属于不同进程的).操作系统不断的从一个线程的执行切换到另一个线程的执行,如此往复,宏观上看来,就好像是多个线程在一起执行.由于这多个线程分属于不同的进程,因此在我们看来,就好像是多个进程在同时执行,这样就实现了多任务

73、三次握手,四次挥手

第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入syn_sent状态,等待服务器确认;
第二次握手:服务器接收到syn包,确认客户端的syn,同时返回一个syn给客户端,进入syn_sent状态;
第三次握手:客户端接收服务器的syn_ack包,并向服务器发送确认包,客户端与服务器进入连接状态,完成三次握手。
四次挥手:
第一次挥手:客户端进程发出连接释放报文,并停止发送数据;
第二次挥手:服务器收到连接释放报文,发出确认报文,服务器进入等待关闭状态;
第三次挥手:客户端接收服务器确认的请求后,客户端进入终止等待状态,等待服务器发送连接释放报文;
第四次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,客户端接收后发送确认,完成四次挥手,连接断开

74、单例模式

  • 某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式
  • 应用场景:
    • 资源共享的情况下,避免由于资源操作时导致的性能或损耗等
    • 控制资源的情况下,方便资源之间的互相通信

创建单例-保证只有一个对象

class Trash(object):
    __instance = None
    
    def __new__(cls,*args,**kwargs):
        # #如果类属性__instance的值为None,
        #那么就创建一个对象,并且赋值为这个对象的引用,保证下次调用这个方法时
        #能够知道之前已经创建过对象了,这样就保证了只有1个对象
        if cls.__instance is None:
            cls.__instance = object.__new__(cls)
         return cls.__instance
    
a= Trash()    
b= Trash()

# 同一内存地址
print(id(b))
print(id(a))

a.age = 19
# 19
print(b.age)

创建单例时,只执行一次init方法

# 实例化一个单例
class Singleton(object):
    __instance = None
    __is_first = True

    def __new__(cls, age, name):
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance

    def __init__(self, age, name):
        if self. __is_first: # 不会再创建第二个对象
            self.age = age
            self.name = name
            Singleton. __is_first = False


a = Singleton(18, "张三")
b = Singleton(28, "张三")

print(id(a))
print(id(b))

# 第二个对象创建失败
print(a.age) # 18
print(b.age) # 18

a.age = 19
print(b.age)

装饰器实现单例

def singleton(cls, *args, **kw):
    instance={}
    def _singleton():
        if cls not in instance:
            instance[cls]=cls(*args, **kw)
        return instance[cls]
    return _singleton
 
@singleton
class test_singleton(object):
    def __init__(self):
        self.num_sum=0
    def add(self):
        self.num_sum=100    

if __name__ == '__main__':
    c1 = test_singleton()
    c2 = test_singleton()
    print(c1)

75、redis的5种数据类型

  • string
  • hash
  • list
  • set
  • zset

76、介绍flask中蓝图和请求钩子

- 第一个钩子:@app.before_first_request
  只在第一次请求之前执行,也就是启动项目,不会执行,只会在第一次有人发起请求时,才会触发这个钩子中的代码。
  全局场景:可以带动一个异步执行的函数,进行一些健康指标的检查,如果发现有异常,则截断后续的请求,将整个Flask应用停止。
- 第二个钩子:@app.before_request
  这是最重要的一个钩子,在每次请求之前可以注入你要的逻辑的钩子。在app下的before_request,过滤的是全部请求。结合Blueprint的before_request,则是过滤该蓝图下的请求。所以我们就可以进行分层过滤,定制化过滤。
  全局的场景包含:共享session的鉴权函数、请求黑白名单过滤、根据endpoint进行请求j等。
  蓝图场景包含api的请求必填字段校验,是否json请求校验,请求的token校验等。
- 第三个钩子:@app.errorhandler
  当访问应用出错时,根据错误响应码,进行一些定制化的操作,如返回一个可爱的404页面。也可以进行一些报错登记。
  场景:可以用redis进行错误请求计数,超过一定量则进行告警。可以重定向到一个定制的错误代码页面等。
- 第四个钩子:@app.context_processor
  这个钩子也很实用,是将一些常量按字典的格式返回,则可以在jinja2的模版中引用。这样就不用在每个视图函数中都render_template中重复去写一次。代码更简洁。
  场景:在html中,直接用{{jidan}}就会在页面显示yao。等同于app.add_template_global('yao',''jidan)
- 第五个钩子:@app.after_request
  和上个钩子类似,差别在于是请求完成时执行,它和之前钩子有点不同,必须传入一个参数来接收响应对象,并在最后return 这个参数,也就是返回响应内容。
  场景:一般用于格式化响应结果,包括响应请求头,响应的格式等。
- 第六个钩子:@app.teardown_request
  和第五个钩子功能类似,在响应销毁时,执行一个绑定的函数。做一些操作。
  区别点在于:
   ●  after_request: 每一个请求之后绑定一个函数,如果请求没有异常。
   ●  teardown_request: 每一个请求之后绑定一个函数,即使遇到了异常。
  场景:销毁DB连接等。
- 第七个钩子:@app.teardown_appcontext
  之前介绍的大部分是请求上下文的钩子,这个属于应用上下文的钩子。不管是否有异常,当APP上下文被移除之后执行的函数, 可以进行数据库的提交或者回滚。
  场景:DB事务操作。

77、Python的第三方库

- re    匹配正则    re.findall
- requests     用来发送求    requests.put
- os    os.remove()  删除一个文件
- time        time time() 返回当前时间的时间戳(1970纪元后经过的浮点秒数)

78、在三次握手和四次挥手中哪个环节更容易受到黑客攻击? 三次握手和四次挥手

浏览器与服务器的通信

浏览器访问:http://www.obcde.com/x/t/z.html



1.DNS解析:www.abcde.com  ->>  DNS  服务器    -->  11.22.33.44

2.浏览器与服务器建立TCP连接

	#三次握手(用来建立连接)

					TCP   报文   (是二进制的数据流)

	1)client    -->    SYN    -->    server     SYN:跟服务器一个请求,代表想跟服务器询问想建立一个链接,请求服务器的同意(报文)
#seq是数据包本身的序列号;ack是期望对方继续发送的那个数据包的序列号。
	2)   client   <--   ACK  +    SYN   <--  server    

	3)   client   -->    ACK 	--> 		server



3.封装    HTTP   request 报文(是一对人能识别的字符串)

4.将报文发送给服务器

5.服务器接收,并解析

6.服务器做出相应处理(逻辑运算、数据存取、数据修改)

7.服务器封装    HTTP Response    报文

8.服务器将报文发送给  浏览器

9.服务器断开与客户端的连接

	#四次挥手

	1.server  -> FIN->   client    FIN(二进制的结束报文)    finally

	2.server  <- ACK <- client     ACK   客户端确认(知道了的接受结束)的报文传给服务器

	3.server  <- FIN <-   client    客户端要验证传输的数据是否全部正确和是否所有数据的全部接受完毕

	4.server  ->  ACK  ->  client  服务器断开连接

10.浏览器接受响应报文

11.解析、呈现

		

	eg:当服务器接受客户端的请求,服务器会在内存中单独开辟一个空间,所以服务器要接受完浏览器的三次挥手  request处理完毕    返回响应的时候就会断开连接

	HTTP    建立在    TCP    基础之上的短连接协议



	TCP    全双工    可以互相的交互    不用协定时间,可以统一时间进行交互

	半双工    :是相互的协议,1时间段是服务器向客户端发送数据,2时间客户端向服务器发送数据





(1)三次握手

三次握手建立连接阐述:

第一次握手:客户端要和服务端进行通信,首先要告知服务端一声,遂发出一个SYN=1的连接请求信号,”服务端哥哥,我想给你说说话”。

第二次握手:当服务端接收到客户端的连接请求,此时要给客户端一个确认信息,”我知道了(ACK),我这边已经准备好了,你现在能连吗(SYN)”。

第三次握手:当客户端收到了服务端的确认连接信息后,要礼貌的告知一下服务端,“好的,咱们开始联通吧(ACK)”。

到此整个建立连接的过程已经结束,接下来就是双方你一句我一句甚至同时交流传递信息的过程了。

(2)四次挥手

四次挥手断开连接阐述:

第一次挥手:双方交流的差不多了,此时客户端也已经结尾了,接下来要断开通信连接,所以告诉服务端“我说完了(FIN)”,此时自身形成等待结束连接的状态。

第二次挥手:服务端知道客户端已经没话说了,服务端此时还有两句心里话要给客户端说,“我知道你说完了(ACK),我再给你说两句,&*……%¥”。

第三次挥手:此时客户端洗耳恭听继续处于等待结束的状态,服务器端也说完了,自身此时处于等待关闭连接的状态,并对告诉客户端,“我说完了,咱们断了吧(FIN)”。

第四次挥手:客户端收知道服务端也说完了,也要告诉服务端一声(ACK),因为连接和断开要双方都按下关闭操作才能断开,客户端同时又为自己定义一个定时器,因为不知道刚才说的这句话能不能准确到达服务端(网络不稳定或者其他因素引起的网络原因),默认时间定为两个通信的最大时间之和,超出这个时间就默认服务器端已经接收到了自己的确认信息,此时客户端就关闭自身连接,服务器端一旦接收到客户端发来的确定通知就立刻关闭服务器端的连接

到此为止双方整个通信过程就此终结。这里要声明一下:断开链接不一定就是客户端,谁都可以先发起断开指令,另外客户端和服务端是没有固定标准的,谁先发起请求谁就是客户端。

79、为什么要归一化

1、提升模型的收敛速度
2.提升模型的精度
归一化的另一好处是提高精度,这在涉及到一些距离计算的算法时效果显著

作用:对于不同的特征向量,比如年龄、购买量、购买额,在数值的量纲上相差十倍或者百千倍。如果不归一化处理,就不容易进行比较、求距离,模型参数和正确度精确度就会受影响,甚至得不出正确的结果。

1.为什么要归一化?作用 2.PCA是用来干什么的? 3.讲一下CNN的应用以及有哪几种算法? 4.讲一下GBDT和LGB的区别? 5.工作中用到最多的算法?讲一下逻辑回归的原理? 6.对FLask印象最深的点是什么? 7.redis消息队列? 8.讲一下反反爬虫的机制? 9.知道在线学习吗?online learning rate 10.讲一下best-ks和Auc,他们之间的关系? 11.讲一下协同过滤算法 12.说一下催收评分卡的建立?对应客户群有哪些,特征的选择,目标值怎么定义? 13.有独立做过项目吗? 14.申请评分卡的流程? 












你可能感兴趣的:(面试,python,mysql,数据库,django)