0,python2和python3的区别html
""" .1 默认解释器编码:py2-> ascii ; py3->utf-8 .2 字符串和字节(*****) py2: unicode str = bytes py3: str,字符串 bytes,字节 .3 经典类和新式类 py2: - 经典 - 新式(直接或间接继承object) py3: - 新式 .4 yield from ... """
20、python2和python3区别?列举5个java
一、Python3 使用 print 必需要以小括号包裹打印内容,好比 print('hi')python
Python2 既可使用带小括号的方式,也可使用一个空格来分隔打印内容,好比 print 'hi'mysql
二、python2 range(1,10)返回列表,python3中返回迭代器,节约内存4 linux
四、python2中unicode表示字符串序列,str表示字节序列web
python3中str表示字符串序列,byte表示字节序列ajax
五、python2中为正常显示中文,引入coding声明,python3中不须要算法
六、python2中是raw_input()函数,python3中是input()函数sql
1,什么是GIL?数据库
GIL全局解释器锁
在同一个进程里的每个线程同一时间只能有一个线程访问cpu,只要在多线程/进程之间用到全局 变量就要加上锁
2,python中@staticmethod和@classmethod的区别?
@classmethod(cls):类方法,类名去调用,它会将类空间传给cls
@staticmethod():静态方法,不用传入类空间,对象空间的方法,至关于普通函数.
3,python里面如何拷贝一个对象,并解释深浅拷贝
浅拷贝:第一层建立的是新的内存地址,而从第二层开始,指向的都是同一个内存地址,因此,对于第二层及更深的层数来讲,保持一致性
深拷贝:彻底独立(复制其数据对象完彻底全放独立的一个内存,彻底拷贝,数据不共享)
4,python里面search()和math()的区别
search():从左到右找,找到第一个就返回,找不到返回None match():从开头找,找不到报错,至关于在前面加个"^"
5,简述迭代器生成器以及他们的区别
迭代器就是用于迭代操做的的对象,听从迭代协议(内部实现了__iter__()和__next__()方法,能够像列表(可迭代对象,只有__iter__()方法)同样迭代获取其中的值,与列表不一样的是,构建迭代器的时候,不像列表同样一次性把数据加到内存,而是以一种延迟计算的方式返回元素,即调用next方法时候返回此值。
迭代器取值:__next__,或者for循环
生成器本质上也是一个迭代器,本身实现了可迭代协议,与生成器不一样的是生成器的实现方式不一样,能够经过生成器表达式和生成器函数两种方式实现,代码更简洁。生成器和迭代器都是惰性可迭代对象,只能遍历一次,数据取完抛出Stopiteration异常
生成式取值:一个yield对应一个next
6,什么是协程,python的协程是如何实现的
协程:能在一条线程的基础上,在多个任务之间互相切换
协程的实现:
import gevent def test1(): print(1,2) gevent.sleep(0)#执行到这里的时候切换去函数test2 print(3,4) def test2(): print(5,6) gevent.sleep(0) print(7,8) gevent.joinall( [gevent.spawn(test1),gevent.spawn(test2)] )#在函数test1等待的时候,协程去执行了函数test2
7,什么是装饰器,请用装饰器实现singleton
装饰器:装饰器的本质是闭包函数,功能,在不改变原函数的基础上,为原函数增长一些额外的功能
# 使用装饰器实现单例模式 def singleton(cls, *args, **kwargs): instance = {} def _instance(): if cls not in instance: instance[cls] = cls(*args, *kwargs) return instance[cls] return _instance @singleton class Test_singleton: def __init__(self): self.num = 0 def add(self): self.num = 99 ts1 = Test_singleton() ts2 = Test_singleton() print(ts1) print(ts2)
8,请使用python实现快速排序
一行代码实现: quick_sort = lambda array: array if len(array) <= 1 else quick_sort([item for item in array[1:] if item <= array[0]]) + [array[0]] + quick_sort([item for item in array[1:] if item > array[0]])
#常见快排 def quick_sort(array, left, right): if left >= right: return low = left high = right key = array[low] while left < right: while left < right and array[right] > key: right -= 1 array[left] = array[right] while left < right and array[left] <= key: left += 1 array[right] = array[left] array[right] = key quick_sort(array, low, left - 1) quick_sort(array, left + 1, high)
#算法中的快排 def quick_sort(array, l, r): if l < r: q = partition(array, l, r) quick_sort(array, l, q - 1) quick_sort(array, q + 1, r) def partition(array, l, r): x = array[r] i = l - 1 for j in range(l, r): if array[j] <= x: i += 1 array[i], array[j] = array[j], array[i] array[i + 1], array[r] = array[r], array[i+1] return i + 1
9,简述select和epoll的原理和区别
select原理概述 调用select时,会发生如下事情: 从用户空间拷贝fd_set到内核空间; 注册回调函数__pollwait; 遍历全部fd,对所有指定设备作一次poll(这里的poll是一个文件操做,它有两个参数,一个是文件fd自己,一个是当设备还没有就绪时调用的回调函数__pollwait,这个函数把设备本身特有的等待队列传给内核,让内核把当前的进程挂载到其中); 当设备就绪时,设备就会唤醒在本身特有等待队列中的【全部】节点,因而当前进程就获取到了完成的信号。poll文件操做返回的是一组标准的掩码,其中的各个位指示当前的不一样的就绪状态(全0为没有任何事件触发),根据mask可对fd_set赋值; 若是全部设备返回的掩码都没有显示任何的事件触发,就去掉回调函数的函数指针,进入有限时的睡眠状态,再恢复和不断作poll,再做有限时的睡眠,直到其中一个设备有事件触发为止。 只要有事件触发,系统调用返回,将fd_set从内核空间拷贝到用户空间,回到用户态,用户就能够对相关的fd做进一步的读或者写操做了。 epoll原理概述 调用epoll_create时,作了如下事情: 内核帮咱们在epoll文件系统里建了个file结点; 在内核cache里建了个红黑树用于存储之后epoll_ctl传来的socket; 创建一个list链表,用于存储准备就绪的事件。 调用epoll_ctl时,作了如下事情: 把socket放到epoll文件系统里file对象对应的红黑树上; 给内核中断处理程序注册一个回调函数,告诉内核,若是这个句柄的中断到了,就把它放到准备就绪list链表里。 调用epoll_wait时,作了如下事情: 观察list链表里有没有数据。有数据就返回,没有数据就sleep,等到timeout时间到后即便链表没数据也返回。并且,一般状况下即便咱们要监控百万计的句柄,大多一次也只返回不多量的准备就绪句柄而已,因此,epoll_wait仅须要从内核态copy少许的句柄到用户态而已。 对比 select缺点: 最大并发数限制:使用32个整数的32位,即32*32=1024来标识fd,虽然可修改,可是有如下第二点的瓶颈; 效率低:每次都会线性扫描整个fd_set,集合越大速度越慢; 内核/用户空间内存拷贝问题。 epoll的提高: 自己没有最大并发链接的限制,仅受系统中进程能打开的最大文件数目限制; 效率提高:只有活跃的socket才会主动的去调用callback函数; 省去没必要要的内存拷贝:epoll经过内核与用户空间mmap同一块内存实现。 固然,以上的优缺点仅仅是特定场景下的状况:高并发,且任一时间只有少数socket是活跃的。 若是在并发量低,socket都比较活跃的状况下,select就不见得比epoll慢了(就像咱们经常说快排比插入排序快,可是在特定状况下这并不成立)。
10,简述python的垃圾回收机制
垃圾回收 Python的GC模块主要运用了引用计数来跟踪和回收垃圾。在引用计数的基础上,还能够经过“标记-清除”解决容器对象可能产生的循环引用的问题。经过分代回收以空间换取时间进一步提升垃圾回收的效率。 引用计数 原理:当一个对象的引用被建立或者复制时,对象的引用计数加1;当一个对象的引用被销毁时,对象的引用计数减1,当对象的引用计数减小为0时,就意味着对象已经再没有被使用了,能够将其内存释放掉。 优势:引用计数有一个很大的优势,即实时性,任何内存,一旦没有指向它的引用,就会被当即回收,而其余的垃圾收集技术必须在某种特殊条件下才能进行无效内存的回收。 缺点:可是它也有弱点,引用计数机制所带来的维护引用计数的额外操做与Python运行中所进行的内存分配和释放,引用赋值的次数是成正比的,这显然比其它那些垃圾收集技术所带来的额外操做只是与待回收的内存数量有关的效率要低。同时,引用技术还存在另一个很大的问题-循环引用,由于对象之间相互引用,每一个对象的引用都不会为0,因此这些对象所占用的内存始终都不会被释放掉。以下: a = [] b = [] a.append(b) b.append(a) print a [[[…]]] print b [[[…]]] 标记-清除 标记-清除只关注那些可能会产生循环引用的对象,显然,像是PyIntObject、PyStringObject这些不可变对象是不可能产生循环引用的,由于它们内部不可能持有其它对象的引用。Python中的循环引用老是发生在container对象之间,也就是可以在内部持有其它对象的对象,好比list、dict、class等等。这也使得该方法带来的开销只依赖于container对象的的数量??? 原理:1. 寻找跟对象(root object)的集合做为垃圾检测动做的起点,跟对象也就是一些全局引用和函数栈中的引用,这些引用所指向的对象是不可被删除的;2. 从root object集合出发,沿着root object集合中的每个引用,若是可以到达某个对象,则说明这个对象是可达的,那么就不会被删除,这个过程就是垃圾检测阶段;3. 当检测阶段结束之后,全部的对象就分红可达和不可达两部分,全部的可达对象都进行保留,其它的不可达对象所占用的内存将会被回收,这就是垃圾回收阶段。(底层采用的是链表将这些集合的对象链接在一块儿) 缺点:标记和清除的过程效率不高。 分代回收 原理:将系统中的全部内存块根据其存活时间划分为不一样的集合,每个集合就成为一个“代”,Python默认定义了三代对象集合,垃圾收集的频率随着“代”的存活时间的增大而减少。也就是说,活得越长的对象,就越不多是垃圾,就应该减小对它的垃圾收集频率。那么如何来衡量这个存活时间:一般是利用几回垃圾收集动做来衡量,若是一个对象通过的垃圾收集次数越多,能够得出:该对象存活时间就越长。
11,写一个简单的python socket编程
server端: import socket sk = socket.socket() # 建立客户套接字 sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 sk.listen() #监听连接 conn,addr = sk.accept() #接受客户端连接 ret = conn.recv(1024) #接收客户端信息 print(ret) #打印客户端信息 conn.send(b'hi') #向客户端发送信息 conn.close() #关闭客户端套接字 sk.close() #关闭服务器套接字(可选) client端: import socket sk = socket.socket() # 建立客户套接字 sk.connect(('127.0.0.1',8898)) # 尝试链接服务器 sk.send(b'hello!') ret = sk.recv(1024) # 对话(发送/接收) print(ret) sk.close() # 关闭客户套接字
12,下面是我输出结果是什么?
#下面代码会输出什么 def f(x,l=[]): for i in range(x): l.append(i*i) print(l) f(2) #[0, 1] f(3,[3,2,1]) #[3, 2, 1, 0, 1, 4] f(3) #[0, 1, 0, 1, 4]
#下面代码会输出什么 class Parent(object): x=1 class Child1(Parent): pass class Child2(Parent): pass print(Parent.x,Child1.x,Child2.x) #1 1 1 print(Parent.x,Child1.x,Child2.x) #1 2 1 Parent.x=3 print(Parent.x,Child1.x,Child2.x) #3 2 3[6, 6, 6, 6]
#下面代码会输出什么 def multipliers(): return [lambda x:i*x for i in range(4)] print([m(2) for m in multipliers()]) #[6, 6, 6, 6]
13,Git的经常使用命令
14,列表去重(不使用set,用基本的方法实现):list=[9,4,2,5,8,4,5,3]
def quchong(list1): list2=[]; for i in list1: if i not in list2: list2.append(i); print(list2); list1 = [9, 4, 2, 5, 8,4,5,3]; quchong(list1)
15,单例模式实现
import threading import time class Foo(object): _instance = None _lock = threading.RLock() def __new__(cls, *args, **kwargs): if cls._instance: return cls._instance with cls._lock: if not cls._instance: cls._instance = object.__new__(cls) return cls._instance def task(): obj = Foo() print(obj) for i in range(10): t = threading.Thread(target=task) t.start() time.sleep(100) obj = Foo()
16,python自带的数据类型
数字、字符串、Bytes、列表、元组、字典、集合、布尔等
17,说说==以及is的区别
==比较数值
is比较内存地址
18,python函数中*args和**kwargs这两个参数是什么意思
1:*args的功能:------接收多个位置参数,转换成元组tuple形式 2:**kwargs的功能------接收多个关键字参数,转换成字典dict形式 3:位置参数必定要在关键字参数以前,也就是(*args,**kwargs)
19,什么是lambda函数,它有什么好处
什么是lamda函数? lambda 函数是一个能够接收任意多个参数(包括可选参数)而且返回单个表达式值的函数。 (注意:lambda 函数不能包含命令,它们所包含的表达式不能超过一个) lamda函数有什么好处? 1、lambda函数比较轻便,即用即仍,很适合须要完成一项功能,可是此功能只在此一处使用,连名字都很随意的状况下; 2、匿名函数,通常用来给filter,map这样的函数式编程服务; 三、做为回调函数,传递给某些应用,好比消息处理
20,用过的标准包以及第三方包(os以及sys)
标准包:内置模块? """ os time & datetime random hashlib sys re logging json pickle """ # 11. 第三方模块 """ requsts bs4 pymysql pymongo gevent
21,range和xrange的区别
range: range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列。注意这里是生成一个序列。 xrange的用法与range相同,即xrange([start,] stop[, step])根据start与stop指定的范围以及step设定的步长,他所不一样的是xrange并非生成序列,而是做为一个生成器。即他的数据生成一个取出一个。 因此相对来讲,xrange比range性能优化不少,由于他不须要一会儿开辟一块很大的内存,特别是数据量比较大的时候。 注意:1、xrange和range这两个基本是使用在循环的时候。 二、 当须要输出一个列表的时候,就必需要使用range了。
22,线程,进程的区别
进程:资源分配的最小单位
线程:CPU调度的最小单位
进程:IO密集型/计算密集型 提升并发,资源浪费. 线程:IO密集型提升并发,多个线程 协程:IO密集型提供并发,1个线程 计算密集型:进程 IO密集型:线程 < 协程
区别:
一、 一个程序中至少有一个进程,一个进程中至少有一个线程;
二、 线程的划分尺度小于进程(占有资源),使得多线程程序的并发性高;
三、 进程运行过程当中拥有独立的内存空间,而线程之间共享内存,从而极大的提升了程序的运行效率
四、 线程不能独立运行,必须存在于进程中
优缺点:
线程开销小,可是不利于资源的管理和保护,而进程反之。
23,描述对python中数据类型列表list,字典 dict,元组 tuple的理解
元组:()用元括弧括起来的一组元素集合。其特色是内容不可变,即一旦定义其长度和内容都是固定的;相似于C询言的数组。如: t = (0, True, ‘a’) 上面就定义了一个包含3个子元素的元组列表,访问元组成员的格式是使用成员下标,如: print t(1) True (理解为C的数组) 列表:[]由中括弧括起来的包含一组元素的集合;其特色是长度和内容均可以改变。定义以下: L = [0, False, ‘l’] 列表能够进行以下操做: 添加元素:L.append(1) 删除元素:del L[0] 插入元素:L.insert(2, 3) 修改元素:L[1] = True (理解为java链表数组) 字典:{}Python中的字典和其它询言的字典是一个意思,是对hashmap的实现;其询法定义为: d = {‘k1’: ‘k’, ‘k2’: ‘k2’} 字典能够有以下操做: 增长键值对:d[‘k3’] = 3 删除键值对:del d[‘k’] 修改键值对:d[‘k2’] = True 获取键值: d[‘k1’]
24,如何删除一个list中的元素,如何删除dict中的一对kv
l1 = ["alex","wusir"]
l1.remove("alex")
dic = {'name':'老男孩','age':56,'hobby':'women'} del dic['name']
25,如何查找一个字符串中特定字符?Find()和index()两个函数有什么差别?
都是经过元素找索引:
find()方法:查找子字符串,若找到返回从0开始的下标值,若找不到返回-1
index方法是在字符串里查找子串第一次出现的位置,若是查找不到子串,会抛出异常,
26,使用过python哪些第三方件?
1.Web框架 Django: 开源Web开发框架,它鼓励快速开发,并遵循MVC设计,开发周期短。 ActiveGrid: 企业级的Web2.0解决方案。 Karrigell: 简单的Web框架,自身包含了Web服务,py脚本引擎和纯python的数据库PyDBLite。 Tornado: 一个轻量级的Web框架,内置非阻塞式服务器,并且速度至关快 webpy: 一个小巧灵活的Web框架,虽然简单可是功能强大。 CherryPy: 基于Python的Web应用程序开发框架。 Pylons: 基于Python的一个极其高效和可靠的Web开发框架。 Zope: 开源的Web应用服务器。 TurboGears: 基于Python的MVC风格的Web应用程序框架。 Twisted: 流行的网络编程库,大型Web框架。 Quixote: Web开发框架。 2.科学计算 Matplotlib: 用Python实现的类matlab的第三方库,用以绘制一些高质量的数学二维图形。 SciPy: 基于Python的matlab实现,旨在实现matlab的全部功能。 NumPy: 基于Python的科学计算第三方库,提供了矩阵,线性代数,傅立叶变换等等的解决方案。 3.GUI PyGtk: 基于Python的GUI程序开发GTK+库。 PyQt: 用于Python的QT开发库。 WxPython: Python下的GUI编程框架,与MFC的架构类似。 4.其它 BeautifulSoup: 基于Python的HTML/XML解析器,简单易用。 PIL: 基于Python的图像处理库,功能强大,对图形文件的格式支持普遍。 PyGame: 基于Python的多媒体开发和游戏软件开发模块。 Py2exe: 将python脚本转换为windows上能够独立运行的可执行程序。
27,描述一下MVC架构
MVC是一种架构设计模式,是一种设计理念。是为了达到分层设计的目的,从而使代码解耦,便于维护和代码的复用。MVC是3个单词的缩写,全称:Model-View-Controller(模型-视图-控制器)。
一、Model
模型层,能够简单理解就是数据层,用于提供数据。在项目中,(简单理解)通常把数据访问和操做,好比将对象关系映射这样的代码做为Model层,也就是对数据库的操做这一些列的代码做为Model层。好比代码中咱们会写DAO和DTO类型的代码,那这个DAO和DTO咱们能够理解为是属于Model层的代码。
二、View
视图层,就是UI界面,用于跟用户进行交互。通常全部的JSP、Html等页面就是View层。
三、Controller
控制层,Controller层的功能就是将Model和View层进行关联。好比View主要是显示数据的,可是数据又须要Model去访问,这样的话,View会先告诉Controller,而后Controller再告诉Model,Model请求完数据以后,再告诉View。这样View就能够显示数据了。
28,描述一下表与视图的理解
数据库中的数据都是存储在表中的,而视图只是一个或多个表依照某个条件组合而成的结果集,通常来讲你能够用update,insert,delete等sql语句修改表中的数据,而对视图只能进行select操做。可是也存在可更新的视图,对于这类视图的update,insert和delete等操做最终会做用于与其相关的表中数据。所以,表是数据库中数据存储的基础,而视图只是为了知足某种查询要求而创建的一个对象。
表是物理存在的,你能够理解成计算机中的文件!
视图是虚拟的内存表,你能够理解成Windows的快捷方式!
区别:一、视图是已经编译好的sql语句。而表不是
二、视图没有实际的物理记录。而表有。
三、表是内容,视图是窗口
四、表只用物理空间而视图不占用物理空间,视图只是逻辑概念的存在,表能够及时对它进行修改,但视图只能有建立的语句来修改
五、表是内模式,视图是外模式
六、视图是查看数据表的一种方法,能够查询数据表中某些字段构成的数据,只是一些SQL语句的集合。从安全的角度说,视图能够不给用户接触数据表,从而不知道表结构。
七、表属于全局模式中的表,是实表;视图属于局部模式的表,是虚表。
八、视图的创建和删除只影响视图自己,不影响对应的基本表。
29,有0<x<=10,10<x<=20,20<x<=30,......,190<x<=200,200<x这样的 21个区间分别对应1-21二十一个级别,请编写一个函数level(x)根据输入数值返回对应级别.
30,有一个数据结构以下所示,请编写一个函数从该结构数据中返回由指定的字段和对应的值组成的字典,若是指定字段不存在,则跳过该字段.
data:{"time":"2016-08-05T13:13:05",
"some_id":"ID1234",
"grp1":{"fld1":1,
"fld2":2},
"xxx2":{"fld3":0,
"fld5":0.4},
"fld6":11,
"fld7":7,
"fld46":8}
fields:由"|"链接的一以"fld"开头的字符串,如:fld2|fld3|fld7|fld19
def select(data,fields):
#Todo:implementation
return result
data={'time':'2016-08-05T13;13:05', 'some_ID':'ID1234', 'graps1':{'fld1':1,'fld2':2}, 'xxx2':{'fld3':0,'fld5':0.4}, 'fld6':11, 'fld7':7, 'fld':8 } # 类递归思想 # 栈的思想 fields = 'fld2|fld3|fld7|fld9' fields_lst = fields.split('|') #['fld2', 'fld3', 'fld7', 'fld9'] result = {} data_lst = [1] while data != 1: for key in data: if key in fields_lst: result[key] = data[key] if type(data[key]) == dict: data_lst.append(data[key]) data = data_lst.pop() print(result)
#思路一: def select(data,fields): result = {} field_lst = fields.split('|') for key in data: if key in field_lst: result[key] = data[key] elif type(data[key]) == dict: res = select(data[key],fields) result.update(res) return result data={"time":"2016-08-05T13:13:05", "some_id":"ID1234", "grp1":{ "fld1":1,"fld2":2}, "xxx2":{ "fld3":0,"fld5":0.4}, "fld6":11, "fld7":7, "fld46":8} fields = 'fld2|fld3|fld7|fld19' print(select(data,fields))
#思路二: def select(data,fields,result = {}): field_lst = fields.split('|') for key in data: if key in field_lst: result[key] = data[key] elif type(data[key]) == dict: select(data[key], fields) return result data={"time":"2016-08-05T13:13:05", "some_id":"ID1234", "grp1":{ "fld1":1,"fld2":2}, "xxx2":{ "fld3":0,"fld5":0.4}, "fld6":11, "fld7":7, "fld46":8} fields = 'fld2|fld3|fld7|fld19' select(data,fields) print(select(data,fields))
31,斐波契纳数列1,2,3,5,8,13,21......根据这样的规律,编程求出400万之内最大的斐波契纳数,并求出它是第几个斐波契纳数
li=[1,2] while li[-1]<4000000: li.append(li[-1]+li[-2]) del li[-1] print(li[-1]) print(len(li))
def func(x): if x <= 3: return x else: first = 2 second = 3 for i in range(3,x-1): value = first + second first = second second = value return first+second print func(32)
32,上机编程实现如下功能:
dicta = {"a":1,"b":2,"c":3,"d":4,"f":"hello"}
dictb = {"b":3,"d":5,"e":7,"m":9,"k":"world"}
要求写一段代码,实现两个字典的相加,不一样的key对应的值保留,相同的key对应的值相加后保留,若是是字符串就拼接,如上示例获得结果为:
dictc={"a":1,"b":5,"c";3,"d":9,"e":7,"m":9,"f":"hello","k":"world"}
dicta={'a':1,'b':2,'c':3,'d':4,'f':'hello'} dictb={'b':3,'d':5,'e':7,'m':9,'k':'world'} dic={} for key1 in dicta: for key2 in dictb: if key1==key2: dic[key1]=dicta[key1]+dictb[key2] for a in dicta: if a not in dic: dic[a]=dicta[a] for b in dictb: if b not in dic: dic[b]=dictb[b] print(dic)
3、Python部分
一、 __new__.__init__区别,如何实现单例模式,有什么优势
__new__是一个静态方法,__init__是一个实例方法
__new__返回一个建立的实例,__init__什么都不返回
__new__返回一个cls的实例时后面的__init__才能被调用
当建立一个新实例时调用__new__,初始化一个实例时调用__init__
二、深浅拷贝
浅拷贝只是增长了一个指针指向一个存在的地址,而深拷贝是增长一个指针而且开辟了新的内存,这个增长的指针指向这个新的内存,
采用浅拷贝的状况,释放内存,会释放同一内存,深拷贝就不会出现释放同一内存的错误
三、HTTP/IP相关协议,分别位于哪层
http协议是超文本传输协议,http协议是基于TCP/IP通讯协议来传递数据
http协议工做与c/s架构上,浏览器做为http的客户端经过URL向http服务端即web服务器发送所用请求。web服务器收到全部请求后,向客户端发送响应信息,
http特色是短链接,无状态
地址栏键输入URL,按下回车以后经历了什么?
1.浏览器向DNS服务器请求解析该URL中的域名所对应的IP地址
2.解析出IP地址后,根据IP地址和默认端口80,和服务器创建TCP链接
3.浏览器发出读取文件的http请求,该请求报文做为TCP三次握手的第三个报文的数据发送给服务器
4.服务器对浏览器请求作出响应,并把对应的html文件发送给浏览器
5.释放TCP链接
6.浏览器将该HMTL渲染并显示内容
四、TCP/UDP区别
TCP协议是面向链接,保证高可靠性(数据无丢失,数据无失序,数据无错误,数据无重复达到)传输层协议
UDP:数据丢失,无秩序的传输层协议(qq基于udp协议)
五、webscoket
websocket是基于http协议的,可持续化链接
轮询:浏览器每隔几秒就发送一次请求,询问服务器是否有新消息
长轮询:客户端发起链接后,若是没有消息,就一直不返回response给客户端,直到有消息返回,返回完以后,客户端再次发起链接
六、RabbitMQ:
服务器端有Erlang语言来编写,支持多种客户端,只会ajax,用于分布式系统中存储转发消息,在易用性、扩展性、高可用性的方面不俗。
connection是RabbitMQ的socket链接,它封装了socket部分相关协议逻辑
connectionFactroy为connection的制造工厂
channel是咱们与RabbitMQ打交道的最重要的一个接口,大部分的业务操做是在chaanel这个接口中完成,包括定义Queue、定义Exchange、
绑定Queue与Exchange,发布消息等
七、装饰器
调用装饰器实际上是一个闭包函数,为其余函数添加附加功能,不修改被修改的源代码和不修改被修饰的方式,装饰器的返回值也是一个函数对象。
好比:插入日志、性能测试、事物处理、缓存、权限验证等,有了装饰器,就能够抽离出大量与函数功能自己无关的雷同代码并继续重用。
八、闭包
1.必须有一个内嵌函数
2.内嵌函数必须引用外部函数的变量(该函数包含对外做用域而不是全局做用域名字的引用)
3.外部函数的返回值必须是内嵌函数
九、迭代器与生成器
迭代可迭代对象对应_iter_(方法)和迭代器对应_next_(方法)的一个过程
生成器:包括含有yield这个关键字,生成器也是迭代器,调动next把函数变成迭代器。
十、classmethod,staticmethod,property
类方法:将类的函数转换成类方法,函数上装饰@classmethod会将函数的自动传值参数改为cls
静态方法:此方法至关于给类扩展一个功能,将类内的函数实例化,给类或对象使用,此时类内的函数就是普通函数,无论是类仍是实例化的对象均可以使用
实例化:类的实例化就会产生一个实例(对象),能够理解为类()把虚拟的东西实例化,获得具体存在的值
十一、经常使用的状态码
200--服务器成功返回网页
204--请求收到,但返回信息为空
304--客户端已经执行了GET,但文件未变化
400--错误请求,如语法错误
403--无权限访问
404--请求的页面不存在
500--服务器产生内部错误
十二、多进程,多线程,协程,GIL
GIL:全局解释器锁,是锁在cpython解释器上,致使同一时刻,同一进程只能有一个线程被执行
多进程:多进程模块multiprocessing来实现,cpu密集型,IO计算型能够用多进程
多线程:多线程模块threading来实现,IO密集型,多线程能够提升效率
协程:依赖于geenlet,对于多线程应用。cpu经过切片的方式来切换线程间的执行,遇到IO操做自动切换,线程切换时须要耗时,
而协成好处没有切换的消耗,没有锁定概念。
进程:是资源管理单位,进行是相互独立的,实现并发和并发
线程:是最小的执行单位,线程的出现为了下降上下文切换的消耗,提供系统的并发性
1三、IO多路复用/异步非阻塞
IO多路复用:经过一种机制,能够监听多个描述符 select/poll/epoll
select:链接数受限,查找配对速度慢,数据由内核拷贝到用户态
poll:改善了链接数,可是仍是查找配对速度慢,数据由内核拷贝到用户态
epoll:epoll是linux下多路复用IO接口,是select/poll的加强版,它能显著提升程序在大量并发链接中只有少许活跃的状况下的系统CPU利用率
异步非阻塞:异步体如今回调上,回调就是有消息返回时告知一声儿进程进行处理。非阻塞就是不等待,不须要进程等待下去,
继续执行其余操做,无论其余进程的状态。
1四、PEP8规范,规范的好处是什么?
1.缩进:4个空实现缩进,尽可能不使用Tab
2.行:没行最大长度不超过79,换行可使用反斜杠
3.命名规范:
4.注释规范:
1五、range-and-xrange
都在循环时使用,xrange内存性能更好,xrange用法与range彻底相同,range一个生成list对象,xrange是生成器
1六、with上下文机制原理
_enter_和_exit_,上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象类中声明_enter_和_exit_方法,
使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工做,无须收到干预
1七、经典类、新式类
经典类遵循:深度优先,python2中
新式类遵循:广度优先,Python3中
1八、有没有一个工具能够帮助查找Python的bug和进行静态的代码分析?
PyChecker是一个Python代码的静态分析工具,它能够帮助查找Python代码的bug,会对代码的复杂度和格式提出警告,
Pylint是另一个工具能够进行codingstandard检查
1九、 Python是如何进行内存管理的
1.对象引用计数:
引用计数增长的状况:
来保持追踪内存中的对象,全部对象都用引用计数,一个对象分配一个新名称
将其放入一个容器中(列表,字典,元祖)
引用计数减小的状况:
使用del语句对对象别名显示的销毁
引用超出做用域或被从新赋值
sys.getrefcount()函数能够得到对象的当前引用计数
2.标记-清除机制
3.分代技术
20、什么是python?使用python有什么好处?
python是一种编程语言,它有对象、模块、线程、异常处理和自动内存管理。它简洁,简单、方便、容易扩展、有许多自带的数据结果,并且它开源
2一、什么是pickling和unpickling?
Pickle模块读入任何python对象,将它们转换成字符串,而后使用dump函数将其转储到一个文件中——这个过程叫作pickling
反之从存储的字符串文件中提取原始python对象的过程,叫作unpickling
2二、python是如何被解释的?
Python是一种解释性语言,它的源代码能够直接运行,Python解释器会将源代码转换成中间语言,以后再翻译成机器码再执行
2三、数组和元祖之间的区别是什么?
数组和元祖之间的区别:数组内容能够被修改,而元祖内容是只读的,不可被修改的,另外元祖能够被哈希,好比做为字典的key
2四、参数按值传递和引用传递是怎么实现的?
python中的一切都是类,全部的变量都是一个对象的引用。引用的值是由函数肯定的,所以没法被改变,可是若是一个对象是能够被修改的,你能够改动对象
2五、Python都有哪些自带的数据结构?
Python自带的数据结构分为可变和不可变的:可变的有:数组、集合、字典,不可变的是:字符串、元祖、整数
2六、什么是python的命名空间?
在python中,全部的名字都存在于一个空间中,它们在改空间中存在和被操做——这就是命名空间,它就好像一个盒子,在每一个变量名字都对应装着一个对象,
当查询变量的时候,会从该盒子里面寻找相应的对象
2七、python中的unittest是什么?
在python中,unittest是python中的单元测试框架,它拥有支持共享搭建、自动测试、在测试中暂停代码、将不一样测试迭代成一组
2八、*args与**kwargs
*args表明位置参数,它会接收任意多个参数并把这些参数做为元祖传递给函数。**kwargs表明的关键字参数,返回的是字典,位置参数必定要放在关键字前面
2九、在Python中什么是slicing?
slicing是一种在有序的对象类型中(数组、元祖、字符串)节选某一段的语法
30、中的docstring是什么?
Python中文档字符串被称为docstring,它在Python中的做用是为函数、模块和类注释生成文档
3一、os与sys区别:
os是模块负责程序与操做系统的交互,提供了访问操做系统底层的接口
sys模块是负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控Python时运行的环境
3二、实现一个单例模式
_new_()在 _init_()以前被调用,用于生成实例对象。利用这个方法和类的属性的特色能够实现设计模式的单例模式。
单例模式是指建立惟一对象,单例模式设计的类只能实例,实例化1个对象
class Singleton(object):
__instance=None
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if Singleton.__instance is None:
Singleton.__instance=object.__new__(cls,*args,**kwargs)
return Singleton.__instance
33、算法(冒泡排序,选择排序,插入排序)
冒泡:首先,列表每两个相邻的数,若是前面的比后边的大,
那么交换这两个数,代码关键点:趟和无序区,
时间复杂度为:O(n2)
import random
def dublue_sort(li):
for i in range(len(li)-1):
exchange= False
for j in range(len(li)-i -1):
if li[j] > li[j+1]:
li[j],li[j+1] = li[j+1],li[j]
exchange = True
if not exchange:
return
return li
li=list(range(100))
random.shuffle(li)
print(li)
print(dublue_sort(li))
选择:一趟遍历记录最小的数,放到第一个位置,再一趟遍历记录剩余列表中最小的数,
继续放置,代码关键点:无序区和最小数的位置,时间复杂度为:O(n2)
def select_sort(li):
for i in range(len(li)-1): #i是趟
min_loc=i
#找i位置到最后位置范围内最小的数
for j in range(i,len(li)):
if li[j] < li[min_loc]:
min_loc = j
#和无序区第一个数做交换
li[min_loc],li[i] = li[i],li[min_loc]
return li
li=list(range(100))
random.shuffle(li)
print(select_sort(li))
插入:列表被分为有序区和无序区两个部分。最初有序区只有一个元素,
每次从无序区选择一个元素,插入到有序区的位置,直到无序区变空,
代码关键点:摸到的牌和手里的牌,时间复杂度为:O(n2)
def insert_sort(li):
for i in range(1,len(li)): #i 表明每次摸到的牌的下标
tmp=li[i]
j = i-1 # j表明手里最后一张牌的下标
while True:
if j < 0 or tmp >= li[j]:
break
li[ j + 1] = li [j]
j -=1
li[j+1] = tmp
li=list(range(100))
print(insert_sort(li))
二分:列表查找:从列表中查找指定元素,输入:列表、待查找元素,输出:元素下标或未查找到元素。
二分查找,从有序列表的候选区data[0:n]开始,经过对待查找的值与候选区中间值的比较,
可使候选区减小一半。时间复杂为:O(logn)
def bin_search(data,val):
low=0
high=len(data)-1
while low <= high :
mid= (low+high) //2
if data[mid] == val:
return mid
elif data[mid] < high :
low = mid + 1
else:
high = mid - 1
return None
print(bin_search([1,2,3,4,5,6,7,8],4))
4、RESTful API设计指南
参考地址:
http://www.ruanyifeng.com/blog/2014/05/restful_api.html
1、协议
API与用户的通讯协议,老是使用HTTPs协议
2、域名
应该尽可能将API部署在专用域名之下
https://api.example.com
若是肯定API很简单,不会有进一步扩展,能够考虑放在主域名下
https://example.org/api/
3、版本
应该将API的版本号放入URL
https://api.example.com/v1/
另外一种作法是:将版本号放在HTTP头信息中,
4、路径
https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees
5、动词
对于资源的具体操做类型,由HTTP动词表示
GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
DELETE(DELETE):从服务器删除资源。
还有两个不经常使用的HTTP动词
GET /zoos:列出全部动物园
POST /zoos:新建一个动物园
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的所有信息)
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
DELETE /zoos/ID:删除某个动物园
GET /zoos/ID/animals:列出某个指定动物园的全部动物
DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
6、过滤信息(Filtering)
若是记录数量不少,服务器不可能都将它们返回给用户,API应该提供参数,过滤返回结果
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪一个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件
7、状态码(Status Code)
200 OK - [GET]:服务器成功返回用户请求的数据,该操做是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操做,该操做是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户获得受权(与401错误相对),可是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操做,该操做是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(好比用户请求JSON格式,可是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再获得的。
422 Unprocesable entity - [POST/PUT/PATCH] 当建立一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将没法判断发出的请求是否成功。
33,海滩上有一堆桃子,五只猴子来分,第一只猴子把这堆桃子平均分红五分,多了一个,这只猴子把多的一个扔到了海里,拿走了一份,第二只猴子把剩下的四堆桃子合在一块儿,又平均分红五分,又多了一个,它一样把多的一个扔到了海里,拿走了一份,第三只,第四只,第五只都是这样作的,问海滩上原来最少有多少桃子.