谁有TITAN显卡的3D模型 下图中谁会死的 谢谢 OBJ MAX格式都行

===============第一部分 Python基础篇(80题)===============
1. 为什么学习Python?
是爱吗?是责任吗?都不是,是TMD穷!
2. 通过什么途径学习的Python?
大街上有人看我骨骼精奇,是万中无一的编程奇才,卖我本《21天精通Python》,然后……
3. Python和Java、PHP、C、C#、C++等其他语言的对比?
PHP是世界上最好的语言,Python多少差点意思
4. 简述解释型和编译型编程语言?
编译型:运行前先由编译器将高级语言代码编译为对应机器的cpu汇编指令集,再由汇编器汇编为目标机器码,生成可执行文件,然最后运行生成的可执行文件。最典型的代表语言为C/C++,一般生成的可执行文件及.exe文件。
解释型:在运行时由翻译器将高级语言代码翻译成易于执行的中间代码,并由解释器(例如浏览器、虚拟机)逐一将该中间代码解释成机器码并执行(可看做是将编译、运行合二为一了)。最典型的代表语言为JavaScript、Python、Ruby和Perl等。
5. Python解释器种类以及特点?
当 从Python官方网站下载并安装好Python2.7后,就直接获得了一个官方版本的解释器:Cpython,这个解释器是用C语言开发的,所以叫 CPython,在命名行下运行python,就是启动CPython解释器,CPython是使用最广的Python解释器。
IPython是基于CPython之上的一个交互式解释器,也就是说,IPython只是在交互方式上有所增强,但是执行Python代码的功能和CPython是完全一样的,好比很多国产浏览器虽然外观不同,但内核其实是调用了IE。
PyPy是另一个Python解释器,它的目标是执行速度,PyPy采用JIT技术,对Python代码进行动态编译,所以可以显著提高Python代码的执行速度。
Jython是运行在Java平台上的Python解释器,可以直接把Python代码编译成Java字节码执行。
IronPython
IronPython和Jython类似,只不过IronPython是运行在微软.Net平台上的Python解释器,可以直接把Python代码编译成.Net的字节码。
在Python的解释器中,使用广泛的是CPython,对于Python的编译,除了可以采用以上解释器进行编译外,技术高超的开发者还可以按照自己的需求自行编写Python解释器来执行Python代码,十分的方便!
6. 位和字节的关系?
来自英文bit,表示二进制位。位是计算机内部数据储存的最小单位,是一个8位二进制数。一个二进制位只可以表示0和1两种状态;两个二进制位可以表示00、01、10、11四种状态;三位二进制数可表示八种状态。
2.字节(byte)
字节来自英文Byte,习惯上用大写的“B”表示。
字节是计算机中数据处理的基本单位。计算机中以字节为单位存储和解释信息,规定一个字节由八个二进制位构成,即1个字节等于8个比特(1Byte=8bit)。八位二进制数最小为,最大为;通常1个字节可以存入一个ASCII码,2个字节可以存放一个汉字国标码。
7. b、B、KB、MB、GB 的关系?
8. 请至少列举5个 PEP8 规范(越多越好)。
缩进/空格/注释/命名等
http://blog.sae.sina.com.cn/archives/4781
9. 通过代码实现进制转换
## 二进制转换成十进制:v = “0b1111011”
## 十进制转换成二进制:v = 18
## 八进制转换成十进制:v = “011”
## 十进制转换成八进制:v = 30
## 十六进制转换成十进制:v = “0x12”
## 十进制转换成十六进制:v = 87
1) 二进制数、转换为十进制数的规律是:把二进制数按位权形式展开多项式和的形式,求其最后的和,就是其对应的十进制数——简称“按权求和”。
2) 十进制整数转换为二进制整数采用&除2取余,逆序排列&法。具体做法是:用2去除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为零时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。
10进制,当然是便于我们人类来使用,我们从小的习惯就是使用十进制,这个毋庸置疑。
2进制,是供计算机使用的,1,0代表开和关,有和无,机器只认识2进制。
16进制,内存地址空间是用16进制的数据表示, 如0x8039326。
10. 请编写一个函数实现将IP地址转换成一个整数。
## 如 10.3.9.12 转换规则为:
## 再将以上二进制拼接起来计算十进制结果:01
ip_addr='192.168.2.10'
# transfer ip to int
def ip2long(ip):
ip_list=ip.split('.')
for i in range(4):
result=result+int(ip_list[i])*256**(3-i)
return result
# transfer int to ip
def long2ip(long):
floor_list=[]
yushu=long
for i in reversed(range(4)):
res=divmod(yushu,256**i)
floor_list.append(str(res[0]))
yushu=res[1]
return '.'.join(floor_list)
a=long2ip(long)
11. python递归的最大层数?
12. 求逻辑运算符的结果
v1 = 1 or 3
v2 = 1 and 3
v3 = 0 and 2 and 1
v4 = 0 and 2 or 1
v5 = 0 and 2 or 1 or 4
v6 = 0 or Flase and 1
真假比 若都真
or选前 and选后
13. ascii、unicode、utf-8、gbk 区别?
http://www.cnblogs.com/zhuwenlubin/p/5131026.html
14. 字节码和机器码的区别?
机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据。
通常意义上来理解的话,机器码就是计算机可以直接执行,并且执行速度最快的代码。
用机器语言编写程序,编程人员要首先熟记所用计算机的全部指令代码和代码的涵义。手编程序时,程序员得自己处理每条指令和每一数据的存储分配和输入输出,还得记住编程过程中每步所使用的工作单元处在何种状态。这是一件十分繁琐的工作,编写程序花费的时间往往是实际运行时间的几十倍或几百倍。而且,编出的程序全是些0和1的指令代码,直观性差,还容易出错。现在,除了计算机生产厂家的专业人员外,绝大多数的程序员已经不再去学习机器语言了。
机器语言是微处理器理解和使用的,用于控制它的操作二进制代码。
8086到Pentium的机器语言指令长度可以从1字节到13字节。
尽管机器语言好像是很复杂的,然而它是有规律的。
存在着多至100000种机器语言的指令。这意味着不能把这些种类全部列出来。
总结:机器码是电脑CPU直接读取运行的机器指令,运行速度最快,但是非常晦涩难懂,也比较难编写,一般从业人员接触不到。
字节码(Bytecode)是一种包含执行程序、由一序列 op 代码/数据对 组成的二进制文件。字节码是一种中间码,它比机器码更抽象,需要直译器转译后才能成为机器码的中间代码。
通常情况下它是已经经过编译,但与特定机器码无关。字节码通常不像源码一样可以让人阅读,而是编码后的数值常量、引用、指令等构成的序列。
字节码主要为了实现特定软件运行和软件环境、与硬件环境无关。字节码的实现方式是通过编译器和虚拟机器。编译器将源码编译成字节码,特定平台上的虚拟机器将字节码转译为可以直接执行的指令。字节码的典型应用为Java bytecode。
字节码在运行时通过JVM(JAVA虚拟机)做一次转换生成机器指令,因此能够更好的跨平台运行。
总结:字节码是一种中间状态(中间码)的二进制代码(文件)。需要直译器转译后才能成为机器码。
15. 三元运算规则以及应用场景?
简化if语句
16. 列举 Python2和Python3的区别?
1. 文件操作:
xreadlines
f = open('x.log','rb')
for line in f.xreadlines():
print(line)
2. 字符串:
str: 字符串
unicode: u&sdfsdf&
3. 默认解释器编码
py2: ascii
py3: utf-8
py2: range/xrange
py2: int / long
7. input/raw_input
py2: yield
py3: yield/yield from
py2: 新式类和经典类
py3: 新式类
17. 用一行代码实现数值交换
18. Python3和Python2中 int 和 long的区别?
python3 彻底废弃了 long+int 双整数实现的方法, 统一为 int , 支持高精度整数运算.
19. xrange和range的区别?
函数说明:和range 的用法完全相同,但是返回的是一个生成器。
20. 文件操作时:xreadlines和readlines的区别?
1) read([size])方法从文件当前位置起读取size个字节,若无参数size,则表示读取至文件结束为止,它范围为字符串对象
2) 从字面意思可以看出,该方法每次读出一行内容,所以,读取时占用内存小,比较适合大文件,该方法返回一个字符串对象。
3) readlines()方法读取整个文件所有行,保存在一个列表(list)变量中,每行作为一个元素,但读取大文件会比较占内存。
21. 列举布尔值为False的常见值?
布尔型,False表示False,其他为True
整数和浮点数,0表示False,其他为True
字符串和类字符串类型(包括bytes和unicode),空字符串表示False,其他为True
序列类型(包括tuple,list,dict,set等),空表示False,非空表示True
None永远表示False
22. 字符串、列表、元组、字典每个常用的5个方法?
split/strip/replace/find/index ...
append/extend/insert/push/pop/reverse/sort ...
len/max/min/count/index ...
keys/values/pop/clear/del ...
- 集合  add/remove/clear/交集&、并集 |、差集 - 
- collections
Python内建的一个集合模块,提供了许多有用的集合类。
1.Counter是一个简单的计数器,例如,统计字符出现的个数;
2.OrderedDict可以实现一个FIFO(先进先出)的dict,当容量超出限制时,先删除最早添加的K
3.deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈;
4.defaultdict使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用
23. lambda表达式格式以及应用场景?
省去函数命名的烦恼
http://www.cnblogs.com/guigujun/p/6134828.html
24. pass的作用?
当你在编写一个程序时,执行语句部分思路还没有完成,这时你可以用pass语句来占位,也可以当做是一个标记,是要过后来完成的代码。
25. arg和kwarg作用
*args:(表示的就是将实参中按照位置传值,多出来的值都给args,且以元组的方式呈现)
**kwargs:(表示的就是形参中按照关键字传值把多余的传值以字典的方式呈现)
http://www.cnblogs.com/xuyuanyuan123/p/6674645.html
26. is和==的区别
is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同。莱布尼茨说过:“世界上没有两片完全相同的叶子”,这个is正是这样的比较,比较是不是同一片叶子(即比较的id是否相同,这id类似于人的身份证标识)。
== 比较的是两个对象的内容是否相等,即内存地址可以不一样,内容一样就可以了。这里比较的并非是同一片叶子,可能叶子的种类或者脉络相同就可以了。默认会调用对象的 __eq__()方法。
27. 简述Python的深浅拷贝以及应用场景?
Python采用基于值得内存管理模式,赋值语句的执行过程是:首先把等号右侧标识的表达式计算出来,然后在内存中找一个位置把值存放进去,最后创建变量并指向这个内存地址。Python中的变量并不直接存储值,而是存储了值的内存地址或者引用
简单地说,浅拷贝只拷贝一层(如果有嵌套),深拷贝拷贝所有层。
一层的情况:
import copy
li1 = [1, 2, 3]
li2 = li1.copy()
li1.append(4)
print(li1, li2)
# [1, 2, 3, 4] [1, 2, 3]
li1 = [1, 2, 3]
li2 = copy.deepcopy(li1)
li1.append(4)
print(li1, li2)
# [1, 2, 3, 4] [1, 2, 3]
多层的情况:
import copy
li1 = [1, 2, 3, [4, 5], 6]
li2 = li1.copy()
li1[3].append(7)
print(li1, li2)
# [1, 2, 3, [4, 5, 7], 6] [1, 2, 3, [4, 5, 7], 6]
li1 = [1, 2, 3, [4, 5], 6]
li2 = copy.deepcopy(li1)
li1[3].append(7)
print(li1, li2)
# [1, 2, 3, [4, 5, 7], 6] [1, 2, 3, [4, 5], 6]
28. Python垃圾回收机制?
Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。
1 引用计数
PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。
简单 实时性 缺点:
维护引用计数消耗资源 循环引用
2 标记-清除机制
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。
3 分代技术
分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。
Python默认定义了三代对象集合,索引数越大,对象存活时间越长。
http://python.jobbole.com/82061/
29. Python的可变类型和不可变类型?
在Python中不可变对象指:一旦创建就不可修改的对象,包括字符串,元组,数字
在Python中可变对象是指:可以修改的对象,包括:列表、字典
30. 求可变数据类型结果
v = dict.fromkeys(['k1','k2'],[])
v['k1'].append(666)
# {'k1': [666], 'k2': [666]}
v['k1'] = 777
# {'k1': 777, 'k2': [666]}
31. 求匿名函数结果
def num():
return[lambda x: i*x for i in range(4)]
print([m(2) for m in num()])
# [6, 6, 6, 6]
32. 列举常见的内置函数?
# 把x转换成浮点数
complex(x) # 转换成复数
# 转换成字符串
# 转换成列表
tuple(x) # 转换成元组
进制相互转换
r= bin(10) #二进制
r= int(10) #十进制
r = oct(10) #八进制
r = hex(10) #十六进制
i= int(&11&,base=10)#进制间的相互转换base后跟 2/8/10/16
chr(x)//返回x对应的字符,如chr(65)返回‘A'
ord(x)//返回字符对应的ASC码数字编号,如ord('A')返回65
abs(),all(),any(),bin(),bool(),bytes(),chr(),dict()dir(),divmod(),enumerate(),eval(),filter(),float(),gloabls(),help(),hex(),id(),input(),int(),isinstance(),len(),list(),locals(),map(),max(),min(),oct(),open(),ord(),pow(),print(),range(),round(),set(),type(),sorted(),str(),sum(),tuple()
33. filter、map、reduce的作用?
filter:对于序列中的元素进行筛选,最终获取符合条件的序列
map:遍历序列,对序列中每个元素进行操作,最终获取新的序列
reduce:对于序列内所有元素进行累计操作
34. 一行代码实现9乘9乘法表
print(&\n&.join(&\t&.join([&%s*%s=%s& %(x,y,x*y) for y in range(1, x+1)]) for x in range(1, 10)) )
35. 如何安装第三方模块?以及用过哪些第三方模块?
- pip包管理器
- 源码安装
- 下载-&解压-&cd 到对应路径
- python setup.py build
- python setup.py install
36. 常用模块都有哪些?
- re/json/logging/os/sys/requests/beautifulsoup4
match和search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;
re.search匹配整个字符串,直到找到一个匹配。
38. 什么是正则的贪婪匹配?
贪婪和非贪婪
正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪则相反,总是尝试匹配尽可能少的字符。在&*&,&?&,&+&,&{m,n}&后面加上?,使贪婪变成非贪婪。
39. 求结果:a. [ i % 2 for i in range(10) ] b. ( i % 2 for i in range(10) )
[ i % 2 for i in range(10) ]
# [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
( i % 2 for i in range(10) )
# &generator object &genexpr& at 0x0FC0&
40. 求结果:a. 1 or 2 b. 1 and 2 c. 1 & (2==2) d. 1 & 2 == 2
41. def func(a,b=[]) 这种写法有什么坑?
def func(a, b=[]):
b.append(a)
s = func(1)
s = func(1)
# 第二次调用的时候 b的初始值是[1]了
42. 如何实现 “1,2,3” 变成 [‘1’,’2’,’3’] ?
list(&1,2,3&.split(','))
43. 如何实现[‘1’,’2’,’3’]变成[1,2,3] ?
[int(x) for x in ['1','2','3']]
44. 比较: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ] 的区别?
前两个列表内是int
最后一个列表内是元组
<h2 id="如何用一行代码生成. 如何用一行代码生成[1,4,9,16,25,36,49,64,81,100] ?
i*i for i in range(1,11)]
46. 一行代码实现删除列表中重复的值 ?
list(set([1, 2, 3, 4, 45, 1, 2, 343, 2, 2]))
47. 如何在函数中设置一个全局变量 ?
在函数中定义的局部变量如果和全局变量同名,则它会隐藏该全局变量。如果想在函数中使用全局变量,则需要使用global进行声明。
48. logging模块的作用?以及应用场景?
logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比print,具备如下优点:
可以通过设置不同的日志等级,在release版本中只输出重要信息,而不必显示大量的调试信息;
print将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据;logging则可以由开发者决定将信息输出到什么地方,以及怎么输出。
https://www.cnblogs.com/testdjt/p/7834856.html
49. 请用代码简单实现一个栈。
# 后进先出
class Stack():
def __init__(self, size):
self.size = size
self.stack = []
self.top = -1
# 入栈之前检查栈是否已满
def push(self, x):
if self.isfull():
raise exception(&stack is full&)
self.stack.append(x)
self.top = self.top + 1
# 出栈之前检查栈是否为空
def pop(self):
if self.isempty():
raise exception(&stack is empty&)
self.top = self.top - 1
self.stack.pop()
def isfull(self):
return self.top + 1 == self.size
def isempty(self):
return self.top == &#39;-1&#39;
def showStack(self):
print(self.stack)
s = Stack(10)
for i in range(6):
s.showStack()
# [0, 1, 2, 3, 4, 5]
for i in range(2):
s.showStack()
# [0, 1, 2, 3]
50. 常用字符串格式化哪几种?
Python的字符串格式化有两种方式:%格式符方式,format方式
51. 简述 生成器、迭代器、可迭代对象 以及应用场景?
如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)刚才说过,很多容器都是可迭代对象,此外还有更多的对象同样也是可迭代对象,比如处于打开状态的files,sockets等等。但凡是可以返回一个 迭代器 的对象都可称之为可迭代对象
那么什么迭代器呢?它是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值,任何实现了 __next__() (python2中实现 next() )方法的对象都是迭代器
生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。生成器(yield)不需要再像上面的类一样写 __iter__() 和 __next__() 方法了,只需要一个 yiled 关键字。 生成器有如下特征是它一定也是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。
http://www.cnblogs.com/yuanchenqi/articles/5769491.html
52. 用Python实现一个二分查找的函数。
def bin_search_rec(data_set, value, low, high):
if low &= high:
mid = (low + high) // 2
if data_set[mid] == value:
return mid
elif data_set[mid] & value:
return bin_search_rec(data_set, value, low, mid - 1)
return bin_search_rec(data_set, value, mid + 1, high)
53. 谈谈你对闭包的理解?
https://www.cnblogs.com/Lin-Yi/p/7305364.html
54. os和sys模块的作用?
os就是一个普通的python库,用来向Python程序提供运行环境,特别是在文件系统、创建新进程、获取操作系统本身的一些信息(比如uname),并屏蔽各种不同操作系统之间的细节差异。
sys模块则是python程序用来请求解释器行为的接口。比如关于调试类的(trace, frames,except)等,profiling类(stats, getsizeof),运行时环境类(python path, stderr, stdout),解释器本身(如version)。inspect某种程度上可以看成是在sys提供的功能上的一个包装。
55. 如何生成一个随机数?
random.randint(a,b)
56. 如何使用python删除一个文件?
删除子目录
os.rmdir( path )
# path: &要删除的子目录&
产生异常的可能原因:
(1) path 不存在
(2) path 子目录中有文件或下级子目录
(3) 没有操作权限或只读
os.remove(
filename )
# filename: &要删除的文件名&
产生异常的可能原因:
filename 不存在
(2) 对filename文件, 没有操作权限或只读。
57. 谈谈你对面向对象的理解?
从三大特性说起:继承、封装、多态
起始就是将很多数据封装到一个对象中,类似于把很多东西放到一个箱子中,
如:一个函数如果好多参数,起始就可以把参数封装到一个对象再传递。
在哪里用过:
- django rest framework中的request对象。
- flask中:ctx_context/app_context对象
如果多个类中都有共同的方法,那么为了避免反复编写,就可以将方法提取到基类中实现,
让所有派生类去继承即可。
在哪里用过?
- 版本、认证、分页
python本身就是多态的,崇尚鸭子模型,只要会呱呱叫的就是鸭子。
def func(arg):
arg.send()
https://www.cnblogs.com/iyouyue/p/8535796.html
58. Python面向对象中的继承有什么特点?
Python3的继承机制
子类在调用某个方法或变量的时候,首先在自己内部查找,如果没有找到,则开始根据继承机制在父类里查找。
根据父类定义中的顺序,以深度优先的方式逐一查找父类!
继承参数的书写有先后顺序,写在前面的被优先继承。
59. 面向对象深度优先和广度优先是什么?
http://www.liujiangblog.com/course/python/44
60. 面向对象中super的作用?
我们都知道,在子类中如果有与父类同名的成员,那就会覆盖掉父类里的成员。那如果你想强制调用父类的成员呢?使用super()函数!这是一个非常重要的函数,最常见的就是通过super调用父类的实例化方法__init__!
语法:super(子类名, self).方法名(),需要传入的是子类名和self,调用的是父类里的方法,按父类的方法需要传入参数。
def __init__(self, name):
self.name = name
print(&父类的__init__方法被执行了!&)
def show(self):
print(&父类的show方法被执行了!&)
class B(A):
def __init__(self, name, age):
super(B, self).__init__(name=name)
self.age = age
def show(self):
super(B, self).show()
obj = B(&jack&, 18)
obj.show()
61. 是否使用过functools中的函数?其作用是什么?
1.functools.partial
官网文档说的真是不好理解,就当作是把一个函数,绑定部分或者全部参数后生成一个新版本的函数
2.functools.partialwrap
文档说的比较详细,如果不使用这个wraps,那么原始函数的__name__和__doc__都会丢失
https://blog.csdn.net/secretx/article/details/
62. 列举面向对象中带双下划线的特殊方法,如:new、init
__init__ :
构造函数,在生成对象时调用
析构函数,释放对象时使用
__repr__ :
打印,转换
__setitem__ :
按照索引赋值
__getitem__:
按照索引获取值
https://ltoddy.github.io/essay//python-magic-methods.html
63. 如何判断是函数还是方法?
print(isinstance(obj.func, FunctionType))
print(isinstance(obj.func, MethodType))
class Foo(object):
def __init__(self):
self.name = &#39;lcg&#39;
def func(self):
print(self.name)
obj = Foo()
print(obj.func)
# &bound method Foo.func of &__main__.Foo object at 0x000001ABC0F15F98&&
print(Foo.func)
# &function Foo.func at 0x000001ABC1F45BF8&
# ------------------------FunctionType, MethodType------------#
from types import FunctionType, MethodType
obj = Foo()
print(isinstance(obj.func, FunctionType))
print(isinstance(obj.func, MethodType))
print(isinstance(Foo.func, FunctionType))
print(isinstance(Foo.func, MethodType))
# ------------------------------------------------------------#
obj = Foo()
Foo.func(obj)
obj = Foo()
obj.func()
方法,无需传入self参数
函数,必须手动传入self参数
64. 静态方法和类方法区别?
classmethod 必须有一个指向类对象的引用作为第一个参数,而 staticmethod 可以没有任何参数
class Num:
# 普通方法:能用Num调用而不能用实例化对象调用
def one():
print (&#39;1&#39;)
# 实例方法:能用实例化对象调用而不能用Num调用
def two(self):
print (&#39;2&#39;)
# 静态方法:能用Num和实例化对象调用
@staticmethod
def three():
print (&#39;3&#39;)
# 类方法:第一个参数cls长什么样不重要,都是指Num类本身,调用时将Num类作为对象隐式地传入方法
@classmethod
def go(cls):
cls.three()
#Num.two()
#TypeError: two() missing 1 required positional argument: &#39;self&#39;
Num.three()
#TypeError: one() takes 0 positional arguments but 1 was given
65. 列举面向对象中的特殊成员以及应用场景
http://www.cnblogs.com/bainianminguo/p/8076329.html
66. 1、2、3、4、5 能组成多少个互不相同且无重复的三位数
for x in range(1, 6):
for y in range(1, 6):
for z in range(1, 6):
if (x != y) and (y != z) and (z != x):
print(&%d%d%d& % (x, y, z), end=& | &)
print(&%d%d%d& % (x, y, z))
67. 什么是反射?以及应用场景?
反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!
https://www.cnblogs.com/vipchenwei/p/6991209.html
68. metaclass作用?以及应用场景?
metaclass用来指定类是由谁创建的。
类的metaclass 默认是type。我们也可以指定类的metaclass值。
http://www.cnblogs.com/0bug/p/8578747.html
69. 用尽量多的方法实现单例模式。
http://python.jobbole.com/87294/
http://www.cnblogs.com/0bug/p/8576802.html
常用方式:
使用 __new__
使用装饰器(decorator)
使用元类(metaclass)
70. 装饰器的写法以及应用场景。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
def outer(func):
def inner(*args,**kwargs):
print(&认证成功!&)
result = func(*args,**kwargs)
print(&日志添加成功&)
return result
return inner
def f1(name,age):
print(&%s 正在连接业务部门1数据接口......&%name)
# 调用方法
f1(&jack&,18)
http://www.cnblogs.com/iyouyue/p/8934547.html
71. 异常处理写法以及如何主动跑出异常(应用场景)
while True:
x = int(input(&Please enter a number: &))
except ValueError:
print(&Oops!
That was no valid number.
raise主动抛出一个异常
http://www.runoob.com/python3/python3-errors-execptions.html
72. 什么是面向对象的mro
mro就是方法解析顺序。
方法解析顺序Method Resolution Order
参考:http://www.cnblogs.com/0bug/p/8728570.html#_label8
73. isinstance作用以及应用场景?
用于判断一个对象是否是一个类或者其子类的实例。
class b(A):
class c(b):
print(isinstance(bb, A))
print(isinstance(bb, b))
print(isinstance(bb, c))
74. 写代码并实现LeetCode两数之和:
## Given an array of integers, return indices of the two numbers such that they add up to a specific target.You may assume that each input would
## have exactly one solution, and you may not use the same element twice.
## Example:?
Given nums = [2, 7, 11, 15], target = 9,
?Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1]
class Solution:
def twoSum(self,nums, target):
:type nums: List[int]
:type target: int
:rtype: List[int]
#用len()方法取得nums列表长度
n = len(nums)
#x从0到n取值(不包括n)
for x in range(n):
a = target - nums[x]
#用in关键字查询nums列表中是否有a
if a in nums:
#用index函数取得a的值在nums列表中的索引
y = nums.index(a)
#假如x=y,那么就跳过,否则返回x,y
if x == y:
return x,y
https://blog.csdn.net/linfeng886/article/details/
import json
from json import JSONEncoder
from datetime import datetime
class ComplexEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.strftime(&#39;%Y-%m-%d %H:%M:%S&#39;)
return super(ComplexEncoder,self).default(obj)
d = { &#39;name&#39;:&#39;alex&#39;,&#39;data&#39;:datetime.now()}
print(json.dumps(d,cls=ComplexEncoder))
# {&name&: &alex&, &data&: & 19:52:05&}
https://www.cnblogs.com/tkqasn/p/6005025.html
76. json序列化时,默认遇到中文会转换成unicode,如果想要保留中文怎么办?
在序列化时,中文汉字总是被转换为unicode码,在dumps函数中添加参数ensure_ascii=False即可解决。
77. 什么是断言?应用场景?
python assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假
比如我想测试 a==1。就可以用断言。如果我的猜想错误就会抛出异常,可以用于测试一段表达式是否成立。
78. 有用过with statement吗?它的好处是什么?
with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。
79. 使用代码实现查看列举目录下的所有文件。
# 方法一:(不使用os.walk)
def print_directory_contents(sPath):
for sChild in os.listdir(sPath):
sChildPath = os.path.join(sPath, sChild)
if os.path.isdir(sChildPath):
print_directory_contents(sChildPath)
print(sChildPath)
# 方法二:(使用os.walk)
def print_directory_contents(sPath):
for root, _, filenames in os.walk(sPath):
for filename in filenames:
print(os.path.abspath(os.path.join(root, filename)))
print_directory_contents(&#39;已知路径&#39;)
sPath-- 是你所要便利的目录的地址, 返回的是一个三元组(root,dirs,files)。
root 所指的是当前正在遍历的这个文件夹的本身的地址
_ 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)
filenames 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)
80. 简述 yield和yield from关键字。
https://blog.csdn.net/chenbin520/article/details/?locationNum=7&fps=1
===============第二部分 网络编程和并发(34题)===============
1. 简述 OSI 七层协议。
a) 四层协议:应用层、传输层、网络层、网络接口层
b) 五层协议:
应用层:用户使用的应用程序都归属于应用层,作用为规定应用程序的数据格式。
传输层:网络层帮我们找到主机,但是区分应用层的应用就是靠端口,所以传输层就是建立端口到端口的通信。(端口范围0-63为系统占用端口)
网络层:区分不同的广播域或者子网(否则发送一条数据全世界都会受到,是灾难)。
数据链路层:定义电信号的分组方式。
物理层:基于电器特性发送高低点电压(电信号),高电压对应数字1,低电压对应数字0。
c)七层协议:(应用层、表示层、会话层)、传输层、网络层、(数据链路层、物理层)
2. 什么是C/S和B/S架构?
1.什么是C/S结构
C/S (Client/Server)结构,即客户机和服务器结构。它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。
C/S结构可以看做是胖客户端架构。客户端实现绝大多数的业务逻辑处理和界面展示,作为客户端的部分需要承受很大的压力,从分利用客户端的资源,对客户机的要求较高。
其实现可以是客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据库服务器端,客户端通过数据库连接访问服务器端的数据;另一种是Socket服务器端,服务器端的程序通过Socket与客户端的程序通信。
目前大多数应用软件系统都是Client/Server形式的两层结构,由于现在的软件应用系统正在向分布式的Web应用发展,Web和Client/Server 应用都可以进行同样的业务处理,应用不同的模块共享逻辑组件;因此,内部的和外部的用户都可以访问新的和现有的应用系统,通过现有应用系统中的逻辑可以扩展出新的应用系统。这也就是目前应用系统的发展方向。
传统的C/S体系结构虽然采用的是开放模式,但这只是系统开发一级的开放性,在特定的应用中无论是Client端还是Server端都还需要特定的软件支持。由于没能提供用户真正期望的开放环境,C/S结构的软件需要针对不同的操作系统系统开发不同版本的软件,加之产品的更新换代十分快,已经很难适应百台电脑以上局域网用户同时使用。而且代价高, 效率低。
2.什么是B/S结构
B/S(Browser/Server)结构即浏览器和服务器结构。它是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构。在这种结构下,用户工作界面是通过WWW浏览器来实现,极少部分事务逻辑在前端(Browser)实现,但是主要事务逻辑在服务器端(Server)实现,形成所谓三层3-tier结构。这样就大大简化了客户端电脑载荷,减轻了系统维护与升级的成本和工作量,降低了用户的总体成本(TCO)。
B/S结构可以看作是瘦客户端,只是把显示的较少的逻辑交给了Web浏览器,事务逻辑数据处理在放在了Server端,这样就避免了庞大的胖客户端,减少了客户端的压力。B/S结构的系统无须特别安装,只有Web浏览器即可。当然AJAX\Flex等等的普遍使用也有富客户端的发展方向。
以目前的技术看,局域网建立B/S结构的网络应用,并通过Internet/Intranet模式下数据库应用,相对易于把握、成本也是较低的。它是一次性到位的开发,能实现不同的人员,从不同的地点,以不同的接入方式(比如LAN, WAN, Internet/Intranet等)访问和操作共同的数据库;它能有效地保护数据平台和管理访问权限,服务器数据库也很安全 。特别是在JAVA这样的跨平台语言出现之后,B/S架构管理软件更是方便、快捷、高效。
https://blog.csdn.net/sinat_/article/details/
3. 简述 三次握手、四次挥手的流程。
1 三次握手
客户端通过向服务器端发送一个SYN来创建一个主动打开,作为三次握手的一部分。客户端把这段连接的序号设定为随机数 A。
服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK 的确认码应为 A+1,SYN/ACK 包本身又有一个随机序号 B。
最后,客户端再发送一个ACK。当服务端受到这个ACK的时候,就完成了三路握手,并进入了连接创建状态。此时包序号被设定为收到的确认号 A+1,而响应则为 B+1。
2 四次挥手
注意: 中断连接端可以是客户端,也可以是服务器端. 下面仅以客户端断开连接举例, 反之亦然.
客户端发送一个数据分段, 其中的 FIN 标记设置为1. 客户端进入 FIN-WAIT 状态. 该状态下客户端只接收数据, 不再发送数据.
服务器接收到带有 FIN = 1 的数据分段, 发送带有 ACK = 1 的剩余数据分段, 确认收到客户端发来的 FIN 信息.
服务器等到所有数据传输结束, 向客户端发送一个带有 FIN = 1 的数据分段, 并进入 CLOSE-WAIT 状态, 等待客户端发来带有 ACK = 1 的确认报文.
客户端收到服务器发来带有 FIN = 1 的报文, 返回 ACK = 1 的报文确认, 为了防止服务器端未收到需要重发, 进入 TIME-WAIT 状态. 服务器接收到报文后关闭连接. 客户端等待 2MSL 后未收到回复, 则认为服务器成功关闭, 客户端关闭连接.
图解: http://blog.csdn.net/whuslei/article/details/6667471
4. 什么是arp协议?
ARP协议,全称“Address Resolution Protocol”,中文名是地址解析协议,使用ARP协议可实现通过IP地址获得对应主机的物理地址(MAC地址)。
https://www.cnblogs.com/luchuangao/articles/6053742.html
5. TCP和UDP的区别?
收发两端(客户端和服务器端)都要有成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小、数据量小的数据,合并成一个大的数据块,然后进行封包。这样接收端就难于分辨,必须提供拆包机制。
如果利用TCP每次发送数据,就与对方建立连接,然后双方发送完一段数据后,就关闭连接,这样就不会出现粘包问题(因为只有一种包结构,类似于http协议)。关闭连接主要要双方都发送close连接。
如果发送数据无结构,如文件传输,这样发送方只管发送,接收方只管接收存储即可,也不用考虑粘包
如果双方建立连接,需要在连接后一段时间内发送不同结构数据,就需要考虑粘包问题。所以一般可能会在头加一个数据长度之类的包,以确保接收。
对于UDP,不会使用块的合并优化算法。实际上目前认为,是由于UDP支持的是一对多的模式(注意区分不是并发模式),所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中有消息头(消息来源地址,端口等信息),这样对于接收端来说,就容易进行区分处理了,所以UDP不会出现粘包问题。
6. 什么是局域网和广域网?
一、局域网
局域网(Local Area Network),简称LAN,是指在某一区域内由多台计算机互联成的计算机组。“某一区域”指的是同一办公室、同一建筑物、同一公司和同一学校等,一般是方圆几千米以内。局域网可以实现文件管理、应用软件共享、打印机共享、扫描仪共享、工作组内的日程安排、电子邮件和传真通信服务等功能。局域网是封闭型的,可以由办公室内的两台计算机组成,也可以由一个公司内的上千台计算机组成。
二、广域网
广域网(Wide Area Network),简称WAN,是一种跨越大的、地域性的计算机网络的集合。通常跨越省、市,甚至一个国家。广域网包括大大小小不同的子网,子网可以是局域网,也可以是小型的广域网。
三、局域网和广域网的区别
局域网是在某一区域内的,而广域网要跨越较大的地域,那么如何来界定这个区域呢?例如,一家大型公司的总公司位于北京,而分公司遍布全国各地,如果该公司将所有的分公司都通过网络联接在一起,那么一个分公司就是一个局域网,而整个总公司网络就是一个广域网。
7. 为何基于tcp协议的通信比基于udp协议的通信更可靠?
tcp:可靠 对方给了确认收到信息,才发下一个,如果没收到确认信息就重发
udp:不可靠 一直发数据,不需要对方回应
8. 什么是socket?简述基于tcp协议的套接字通信流程。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部。
服务端:创建socket对象,绑定ip端口bind(),
设置最大链接数listen(),
accept()与客户端的connect()创建双向管道, send(), recv(),close()
客户端:创建socket对象,connect()与服务端accept()创建双向管道 ,
send(), recv(),close()
9. 什么是粘包? socket 中造成粘包的原因是什么?
粘包:数据粘在一起,主要因为:接收方不知道消息之间的界限,不知道一次性提取多少字节的数据造成的
数据量比较小,时间间隔比较短,就合并成了一个包,这是底层的一个优化算法(Nagle算法)
10. IO多路复用的作用?
I/O multiplexing就是所谓的select,poll,epoll,也称这种I/O方式为事件驱动I/O(event driven I/O)。
select/epoll的好处就在于单个进程就可以同时处理多个网络连接的I/O。
它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。
I/O 多路复用的特点是通过一种机制使一个进程能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中的任意一个进入读就绪状态,select()函数就可以返回。
多道技术的实现就是为了解决多个程序竞争或者共享同一个资源(比如cpu)的有序调度问题,解决方式即是多路复用。多路复用分为时间上的复用和空间上的复用,空间上的多路复用是指将内存分为几部分,每一部分放一个程序,这样同一时间内存中就有多道程序,前提保证内存是分割;时间上的多路复用是指多个程序需要在一个cpu上运行,不同的程序轮流使用cpu,当某个程序运行的时间过长或者遇到I/O阻塞,操作系统会把cpu分配给下一个程序,保证cpu处于高使用率,实现伪并发。
11. 什么是防火墙以及作用?
http://www.cnblogs.com/loneywang/archive//912029.html
12. select、poll、epoll 模型的区别?
https://www.cnblogs.com/Anker/p/3265058.html
13. 简述 进程、线程、协程的区别 以及应用场景?
什么是进程
进程(有时称为重量级进程)是一个执行中的程序。每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据。同一个程序执行两次,属于是两个不同进程。
什么是线程
线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。
就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机; 运行状态是指线程占有处理机正在运行;
阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。
什么是协程
协程是“微线程”,并非实际存在;是由程序员人为创造出来并控制程序:先执行某段代码、再跳到某处执行某段代码。
如果遇到非IO请求来回切换:性能更低。
如果遇到IO(耗时)请求来回切换:性能高、实现并发(本质上利用IO等待的过程,再去干一些其他的事)
进程池与线程池
基于多进程或多线程实现并发的套接字通信,然而这种方式的缺陷是:服务的开启的进程数或线程数都会随着并发的客户端数目地增多而增多,这对服务端主机带来巨大的压力,于是必须对服务端开启的进程数或线程数加以控制,让机器在一个自己可以承受的范围内运行,这就是进程池或线程池的用途,例如进程池,就是用来存放进程的池子,本质还是基于多进程,只不过是对开启进程的数目加上了限制。
1、进程和线程的区别?
答:进程拥有一个完整的虚拟地址空间,不依赖于线程而独立存在;反之,线程是进程的一部分,没有自己的地址空间,与进程内的其他线程一起共享分配给该进程的所有资源。
比如:开个QQ,开了一个进程;开了迅雷,开了一个进程。在QQ的这个进程里,传输文字开一个线程、传输语音开了一个线程、弹出对话框又开了一个线程。所以运行某个软件,相当于开了一个进程。在这个软件运行的过程里(在这个进程里),多个工作支撑的完成QQ的运行,那么这“多个工作”分别有一个线程。所以一个进程管着多个线程。通俗的讲:“进程是爹妈,管着众多的线程儿子”。
参考自:https://www.zhihu.com/question/
2、为什么说python的线程是伪线程?
答:在python的原始解释器CPython中存在着GIL(Global Interpreter Lock,全局解释器锁),因此在解释执行python代码时,会产生互斥锁来限制线程对共享资源的访问,直到解释器遇到I/O操作或者操作次数达到一定数目时才会释放GIL。
所以,虽然CPython的线程库直接封装了系统的原生线程,但CPython整体作为一个进程,同一时间只会有一个线程在跑,其他线程则处于等待状态。这就造成了即使在多核CPU中,多线程也只是做着分时切换而已。
参考自:https://www.zhihu.com/question/
3、python的append和extend有什么区别?
答:extend()接受一个列表参数,把参数列表的元素添加到列表的尾部,append()接受一个对象参数,把对象添加到列表的尾部。
14. GIL锁是什么鬼?
线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.对于io密集型任务,python的多线程起到作用,但对于cpu密集型任务,python的多线程几乎占不到任何优势,还有可能因为争夺资源而变慢。
解决办法就是多进程和下面的协程(协程也只是单CPU,但是能减小切换代价提升性能).
15. Python中如何使用线程池和进程池?
进程池:就是在一个进程内控制一定个数的线程
基于concurent.future模块的进程池和线程池 (他们的同步执行和异步执行是一样的)
http://www.cnblogs.com/haiyan123/p/7461294.html
16. threading.local的作用?
a. threading.local
作用:为每个线程开辟一块空间进行数据存储。
问题:自己通过字典创建一个类似于threading.local的东西。
4740:{val:0},
4732:{val:1},
4731:{val:3},
b. 自定义Local对象
作用:为每个线程(协程)开辟一块空间进行数据存储。
from greenlet import getcurrent as get_ident
except Exception as e:
from threading import get_ident
from threading import Thread
import time
class Local(object):
def __init__(self):
object.__setattr__(self,&#39;storage&#39;,{})
def __setattr__(self, k, v):
ident = get_ident()
if ident in self.storage:
self.storage[ident][k] = v
self.storage[ident] = {k: v}
def __getattr__(self, k):
ident = get_ident()
return self.storage[ident][k]
obj = Local()
def task(arg):
obj.val = arg
obj.xxx = arg
print(obj.val)
for i in range(10):
t = Thread(target=task,args=(i,))
17. 进程之间如何进行通信?
进程间通信主要包括管道, 系统IPC(包括消息队列,信号,共享存储), 套接字(SOCKET).
管道包括三种:
1)普通管道PIPE, 通常有两种限制,一是单工,只能单向传输;二是只能在父子或者兄弟进程间使用.
2)流管道s_pipe: 去除了第一种限制,为半双工,可以双向传输.
3)命名管道:name_pipe, 去除了第二种限制,可以在许多并不相关的进程之间进行通讯.
18. 什么是并发和并行?
如果某个系统支持两个或者多个动作(Action)同时存在,那么这个系统就是一个并发系统。如果某个系统支持两个或者多个动作同时执行,那么这个系统就是一个并行系统。并发系统与并行系统这两个定义之间的关键差异在于“存在”这个词。
在并发程序中可以同时拥有两个或者多个线程。这意味着,如果程序在单核处理器上运行,那么这两个线程将交替地换入或者换出内存。这些线程是同时“存在”的——每个线程都处于执行过程中的某个状态。如果程序能够并行执行,那么就一定是运行在多核处理器上。此时,程序中的每个线程都将分配到一个独立的处理器核上,因此可以同时运行。
我相信你已经能够得出结论——“并行”概念是“并发”概念的一个子集。也就是说,你可以编写一个拥有多个线程或者进程的并发程序,但如果没有多核处理器来执行这个程序,那么就不能以并行方式来运行代码。因此,凡是在求解单个问题时涉及多个执行流程的编程模式或者执行行为,都属于并发编程的范畴。
摘自:《并发的艺术》 — 〔美〕布雷谢斯
19. 进程锁和线程锁的作用?
线程锁:大家都不陌生,主要用来给方法、代码块加锁。当某个方法或者代码块使用锁时,那么在同一时刻至多仅有有一个线程在执行该段代码。当有多个线程访问同一对象的加锁方法/代码块时,同一时间只有一个线程在执行,其余线程必须要等待当前线程执行完之后才能执行该代码段。但是,其余线程是可以访问该对象中的非加锁代码块的。
进程锁:也是为了控制同一操作系统中多个进程访问一个共享资源,只是因为程序的独立性,各个进程是无法控制其他进程对资源的访问的,但是可以使用本地系统的信号量控制(操作系统基本知识)。
分布式锁:当多个进程不在同一个系统之中时,使用分布式锁控制多个进程对资源的访问。
http://www.cnblogs.com/intsmaze/p/6384105.html
20. 解释什么是异步非阻塞?
同步异步指的是在客户端
同步意味着客户端提出了一个请求以后,在回应之前只能等待
异步意味着 客户端提出一个请求以后,还可以继续提其他请求阻塞
非阻塞 指的是服务器端
阻塞意味着服务器接受一个请求后,在返回结果以前不能接受其他请求
非阻塞意味着服务器接受一个请求后,尽管没有返回结果,还是可以继续接受其他请求
21. 路由器和交换机的区别?
交换机工作于数据链路层,用来隔离冲突域,连接的所有设备同属于一个广播域(子网),负责子网内部通信。
路由器工作于网络层,用来隔离广播域(子网),连接的设备分属不同子网,工作范围是多个子网之间,负责网络与网络之间通信。
https://www.zhihu.com/question/
22. 什么是域名解析?
域名解析是把域名指向网站空间IP,让人们通过注册的域名可以方便地访问到网站的一种服务。IP地址是网络上标识站点的数字地址,为了方便记忆,采用域名来代替IP地址标识站点地址。域名解析就是域名到IP地址的转换过程。域名的解析工作由DNS服务器完成。
23. 如何修改本地hosts文件?
1)hosts文件的位置:C:\windows\system32\drivers\etc,文件夹中找到Hosts文件并用记事本打开。
2)按照 ip地址
域名 的格式添加单独的一行记录。例如
112.124.39.29 www.server110.com
注意,IP地址前面不要有空格,ip地址和域名之间,要有至少1个空格。
修改后,一定要记得保存文件。
3)如何知道域名的IP地址已经生效?
在您的电脑上请按如下步骤操作:开始--&运行--&输入cmd--&ping 域名--&回车查看结果
显示结果类似 Reply from 220.181.31.183: bytes=32 time=79ms TTL=53
220.181.31.183 就是域名的IP地址
* 注意:有些浏览器会保存DNS缓存,比如Chrome。多按几次F5刷新即可。
https://www.cnblogs.com/cl-blogs/p/4160483.html
24. 生产者消费者模型应用场景及优势?
生产者消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
http://www.cnblogs.com/huchong/p/7454756.html
25. 什么是CDN?
CDN主要功能是在不同的地点缓存内容,通过负载均衡技术,将用户的请求定向到最合适的缓存服务器上去获取内容,比如说,是北京的用户,我们让他访问北京的节点,深圳的用户,我们让他访问深圳的节点。通过就近访问,加速用户对网站的访问。解决Internet网络拥堵状况,提高用户访问网络的响应速度。
CDN的全称是Content Delivery Network,即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。
26. LVS是什么及作用?
LVS 是 Linux
Virtual Server ,Linux 虚拟服务器;是一个虚拟的服务器集群【多台机器 LB IP】。LVS 集群分为三层结构:
1) 负载调度器(load balancer):它是整个LVS 集群对外的前端机器,负责将client请求发送到一组服务器[多台LB IP]上执行,而client端认为是返回来一个同一个IP【通常把这个IP 称为虚拟IP/VIP】
2) 服务器池(server pool):一组真正执行client 请求的服务器,一般是我们的web服务器;除了web,还有FTP,MAIL,DNS
3) 共享存储(shared stored):它为 server pool 提供了一个共享的存储区,很容易让服务器池拥有相同的内容,提供相同的服务[不是很理解]
https://blog.csdn.net/caoshuming_500/article/details/8291940
27. Nginx是什么及作用?
Nginx是一个轻量级、高性能、稳定性高、并发性好的HTTP和反向代理服务器。
https://blog.csdn.net/b9x__/article/details/
https://www.cnblogs.com/xiohao/p/6433401.html
28. keepalived是什么及作用?
https://baike.baidu.com/item/Keepalived/?fr=aladdin
29. haproxy是什么以及作用?
https://baike.baidu.com/item/haproxy/5825820
30. 什么是负载均衡?
负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
https://baike.baidu.com/item/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1
31.什么是RPC及应用场景?
RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
32.简述 asynio模块的作用和应用场景。
https://www.cnblogs.com/zhaof/p/8490045.html
33.简述 gevent模块的作用和应用场景。
https://www.cnblogs.com/zcqdream/p/6196040.html
34.twisted框架的使用和应用?
http://www.cnblogs.com/zhiyong-ITNote/p/7360442.html
===============第三部分 数据库和缓存(46题)===============
1. 列举常见的关系型数据库和非关系型都有哪些?
MySQL/SqlServer
MongoDB/Redis
https://db-engines.com/en/ranking
2. MySQL常见数据库引擎及比较?
MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。
InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。
mysql 数据库引擎: http://www.cnblogs.com/0201zcr/p/5296843.html
MySQL存储引擎--MyISAM与InnoDB区别: https://segmentfault.com/a/7211
3. 简述数据三大范式?
第一范式:确保每列的原子性.
如果每列(或者每个属性)都是不可再分的最小数据单元(也称为最小的原子单元),则满足第一范式.
例如:顾客表(姓名、编号、地址、……)其中&地址&列还可以细分为国家、省、市、区等。
第二范式:在第一范式的基础上更进一层,目标是确保表中的每列都和主键相关.
如果一个关系满足第一范式,并且除了主键以外的其它列,都依赖于该主键,则满足第二范式.
例如:订单表(订单编号、产品编号、定购日期、价格、……),&订单编号&为主键,&产品编号&和主键列没有直接的关系,即&产品编号&列不依赖于主键列,应删除该列。
第三范式:在第二范式的基础上更进一层,目标是确保每列都和主键列直接相关,而不是间接相关.
如果一个关系满足第二范式,并且除了主键以外的其它列都不依赖于主键列,则满足第三范式.
为了理解第三范式,需要根据Armstrong公里之一定义传递依赖。假设A、B和C是关系R的三个属性,如果A-〉B且B-〉C,则从这些函数依赖中,可以得出A-〉C,如上所述,依赖A-〉C是传递依赖。
例如:订单表(订单编号,定购日期,顾客编号,顾客姓名,……),初看该表没有问题,满足第二范式,每列都和主键列&订单编号&相关,再细看你会发现&顾客姓名&和&顾客编号&相关,&顾客编号&和&订单编号&又相关,最后经过传递依赖,&顾客姓名&也和&订单编号&相关。为了满足第三范式,应去掉&顾客姓名&列,放入客户表中。
4. 什么是事务?MySQL如何支持事务?
数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
彻底理解数据库事务: http://www.hollischuang.com/archives/898
5. 简述数据库设计中一对多和多对多的应用场景?
一对一关系示例:
一个学生对应一个学生档案材料,或者每个人都有唯一的身份证编号。
一对多关系示例:(下拉单选)
一个学生只属于一个班,但是一个班级有多名学生。
多对多关系示例:(下拉多选)
一个学生可以选择多门课,一门课也有多名学生。
6. 如何基于数据库实现商城商品计数器?
http://www.cnblogs.com/phpcoder/p/4665850.html
7. 常见SQL(必备)
## 详见武沛齐博客:https://www.cnblogs.com/wupeiqi/articles/5729934.html
8. 简述触发器、函数、视图、存储过程?
1)存储过程?
一组为了完成特定功能的SQL 语句集,经编译后存储在数据库。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程在创建时即在服务器上进行编译,所以执行起来比单个SQL语句快,因为调用存储过程比直接向服务端发送大量SQL语句在执行速度快。
对于存储过程,可以接收参数,其参数有三类:
仅用于传入参数用
仅用于返回值用
既可以传入又可以当作返回值
封装一段sql代码,完成一种特定的功能,必须返回结果。其余特性基本跟存储过程相同
3)函数与存储过程的区别?
3.1) 函数有且只有一个返回值,而存储过程不能有返回值。
3.2) 存储过程可以实现很复杂的业务逻辑,函数有很多限制。不能在函数中使用insert,update,delete,create等语句
3.3)存储过程可以调用函数。但函数不能调用存储过程。
3.4)存储过程一般是作为一个独立的部分来调用。而函数可以作为查询语句的一个部分来调用。
视图是基于 SQL 语句的结果集的可视化虚拟表。
视图中的字段来自一个或多个数据库中的真实表的字段。视图并不在数据库中以存储数据值集形式存在,而存在于实际引用的数据库表中,视图的构成可以是单表查询,多表联合查询,分组查询以及计算(表达式)查询等。行和列数据在引用视图时动态生成
5)触发器?
触发器(TRIGGER)与函数类似,需要声明、执行。但是触发器的执行不是由程序调用,而是由事件来触发从而实现执行。对某个表进行【增/删/改】操作的前后如果希望触发某个特定的行为时,可以使用触发器,触发器用于定制用户对表的行进行【增/删/改】前后的行为
9. MySQL索引种类
MySQL目前主要有以下几种索引类型:
1.普通索引
2.唯一索引
3.主键索引
4.组合索引
5.全文索引
https://www.cnblogs.com/luyucheng/p/6289714.html
10. 索引在什么情况下遵循最左前缀的规则?
https://www.cnblogs.com/jamesbd/p/4333901.html
11. 主键和外键的区别?
1.主键是能确定一条记录的唯一标识,比如,一条记录包括身份正号,姓名,年龄。身份证号是唯一能确定你这个人的,其他都可能有重复,所以,身份证号是主键。
2.外键用于与另一张表的关联。是能确定另一张表记录的字段,用于保持数据的一致性。一个表可以有多个外键。
12. MySQL常见的函数?
https://blog.csdn.net/sugang_ximi/article/details/6664748
13. 列举 创建索引但是无法命中索引的8种情况。
- like &#39;%xx&#39;
select * from tb1 where name like &#39;%cn&#39;;
- 使用函数
select * from tb1 where reverse(name) = &#39;wupeiqi&#39;;
select * from tb1 where nid = 1 or email = &#39;&#39;;
特别的:当or条件中有未建立索引的列才失效,以下会走索引
select * from tb1 where nid = 1 or name = &#39;seven&#39;;
select * from tb1 where nid = 1 or email = &#39;&#39; and name = &#39;alex&#39;
- 类型不一致
如果列是字符串类型,传入条件是必须用引号引起来,不然...
select * from tb1 where name = 999;
select * from tb1 where name != &#39;alex&#39;
特别的:如果是主键,则还是会走索引
select * from tb1 where nid != 123
select * from tb1 where name & &#39;alex&#39;
特别的:如果是主键或索引是整数类型,则还是会走索引
select * from tb1 where nid & 123
select * from tb1 where num & 123
- order by
select email from tb1
当根据索引排序时候,选择的映射如果不是索引,则不走索引
特别的:如果对主键排序,则还是走索引:
select * from tb1
https://www.cnblogs.com/iyouyue/p/9004018.html#_label34
14. 如何开启慢日志查询?
https://www.jianshu.com/p/9f9c
15. 数据库导入导出命令(结构+数据)?
- 导出现有数据库数据:
mysqldump -u用户名 -p密码 数据库名称 &导出文件路径
# 结构+数据
mysqldump -u用户名 -p密码 -d 数据库名称 &导出文件路径
- 导入现有数据库数据:
mysqldump -uroot -p密码 数据库名称 & 文件路径
16. 数据库优化方案?
1. 避免全表扫描,首先应考虑在 where 及 orderby 涉及的列上建立索引。
2. 避免在 where 子句中对字段进行 null 值判断,导致引擎放弃使用索引而进行全表扫描
3. 避免在 where 子句中使用 != 或&操作符,引擎将放弃使用索引而进行全表扫描。
4. 避免在 where 子句中使用or 来连接条件
5. 慎用in 和 not, 可以用 exists 代替 in
6. 慎用 like &#39;XXX%&#39;,要提高效率,可以全文检索。
7. 应尽量避免在 where 子句中对字段进行表达式操作,如:
select id from t where num/2=100
应改为select id from t where num=100*2
8. 避免在where子句中对字段进行函数操作
select id from t where substring(name,1,3)=&#39;abc&#39;
select id from t where name like &#39;abc%&#39;
9. 在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。(索引的最左前缀原则)
10. 并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
11. 索引不是越多越好,索引可以提高select 的效率,同时也降低 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引。
12. 任何地方都不要使用 select * from t ,用具体的字段列表代替“*”
13. 避免频繁创建和删除临时表,以减少系统表资源的消耗。
14. 在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
15. 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
数据库中的数据在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大
16. 读写分离。通过数据库配置设置, mysql复制时,产生了多个数据副本(备库),为减少服务器压力,备库用于处理读操作,主库可同时处理读写。备库的复制是异步的,无法实时同步,读写分离的主要难点也在于备库上的脏数据。通常如果使用备库进行读,一般对数据的实时性要求不能太高。
17. 分库、分表。
分库:当数据库中的表太多,可以考虑将表分到不同的数据库
水平分表:将一些列分到另一张表
垂直分表:将历史信息分到另一张表中,很久之前的记录少有查询
18. 利用缓存存储经常被查询的数据。利用redis、memcache
17. char和varchar的区别?
区别一,定长和变长
char 表示定长,长度固定,varchar表示变长,即长度可变。当所插入的字符串超出它们的长度时,视情况来处理,如果是严格模式,则会拒绝插入并提示错误信息,如果是宽松模式,则会截取然后插入。如果插入的字符串长度小于定义长度时,则会以不同的方式来处理,如char(10),表示存储的是10个字符,无论你插入的是多少,都是10个,如果少于10个,则用空格填满。而varchar(10),小于10个的话,则插入多少个字符就存多少个。
varchar怎么知道所存储字符串的长度呢?实际上,对于varchar字段来说,需要使用一个(如果字符串长度小于255)或两个字节(长度大于255)来存储字符串的长度。但是因为他需要有一个prefix来表示他具体bytes数是多少(因为varchar是变长的,没有这个长度值他不知道如何读取数据)。
区别之二,存储的容量不同
对 char 来说,最多能存放的字符个数 255,和编码无关。
而 varchar 呢,最多能存放 65532 个字符。VARCHAR 的最大有效长度由最大行大小和使用的字符集确定。整体最大长度是 65,532字节
18. 简述MySQL的执行计划?
EXPLAIN命令是查看优化器如何决定执行查询的主要方法。可以帮助我们深入了解MySQL的基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及当运行SQL语句时哪种策略预计会被优化器采用。
http://www.cnblogs.com/clsn/p/8087501.html#auto_id_20
19. 在对name做了唯一索引前提下,简述limit 1 作用
select * from tb where name = ‘Oldboy-Wupeiqi’
select * from tb where name = ‘Oldboy-Wupeiqi’
是这样的的,用where条件过滤出符合条件的数据的同时,进行计数,比如limit 1,那么在where过滤出第1条数据后,他就会直接把结果select出来返回给你,整个过程就结束了。
20. 1000w条数据,使用limit offset 分页时,为什么越往后翻越慢?如何解决?
先查主键,在分页。
select * from tb where id in (
select id from tb where limit 10 offset 30
按照也无需求是否可以设置只让用户看200页
记录当前页
数据ID最大值和最小值
在翻页时,根据条件先进行筛选;筛选完毕之后,再根据limit offset 查询。
select * from (select * from tb where id & ) as B limit 10 offset 0
如果用户自己修改页码,也可能导致慢;此时对url种的页码进行加密(rest framework )
21. 什么是索引合并?
1、索引合并是把几个索引的范围扫描合并成一个索引。
2、索引合并的时候,会对索引进行并集,交集或者先交集再并集操作,以便合并成一个索引。
3、这些需要合并的索引只能是一个表的。不能对多表进行索引合并。
简单的说,索引合并,让一条sql可以使用多个索引。对这些索引取交集,并集,或者先取交集再取并集。从而减少从数据表中取数据的次数,提高查询效率。
22. 什么是覆盖索引?
http://www.cnblogs.com/chenpingzhao/p/4776981.html
23. 简述数据库读写分离?
读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。
https://blog.csdn.net/xybelieve1990/article/details/
24. 简述数据库分库分表?(水平、垂直)
见23问题链接
https://blog.csdn.net/xlgen157387/article/details/
25. redis和memcached比较?
使用redis有哪些好处? 
(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
(2) 支持丰富数据类型,支持string,list,set,sorted set,hash
(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
(4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除
redis相比memcached有哪些优势?   
(1) memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
(2) redis的速度比memcached快很多 (3) redis可以持久化其数据
Memcache与Redis的区别都有哪些?
1)、存储方式 Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis有部份存在硬盘上,这样能保证数据的持久性。
2)、数据支持类型 Memcache对数据类型支持相对简单。 Redis有复杂的数据类型。
3)、使用底层模型不同 它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。 Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
redis与 memcached相比,redis支持key-value数据类型,同时支持list、set、hash等数据结构的存储。
redis支持数据的备份,即master-slave模式的数据备份。
redis支持数据的持久化。
redis在很多方面支持数据库的特性,可以这样说他就是一个数据库系统,而memcached只是简单地K/V缓存。
它们在性能方面差别不是很大,读取方面尤其是针对批量读取性能方面memcached占据优势。当然redis也有他的优点,如持久性、支持更多的数据结构。
所以在选择方面如果有持久方面的需求或对数据类型和处理有要求的应该选择redis。
如果简单的key/value 存储应该选择memcached。
26. redis中数据库默认是多少个db 及作用?
Redis默认支持16个数据库(可以通过配置文件支持更多,无上限),可以通过配置databases来修改这一数字。客户端与Redis建立连接后会自动选择0号数据库,不过可以随时使用SELECT命令更换数据库
Redis支持多个数据库,并且每个数据库的数据是隔离的不能共享,并且基于单机才有,如果是集群就没有数据库的概念。
27. python操作redis的模块?
https://www.cnblogs.com/Eva-J/p/5152841.html
28. 如果redis中的某个列表中的数据量非常大,如果实现循环显示每一个值?
通过scan_iter分片取,减少内存压力
scan_iter(match=None, count=None)增量式迭代获取redis里匹配的的值
# match,匹配指定key
# count,每次分片最少获取个数
r = redis.Redis(connection_pool=pool)
for key in r.scan_iter(match=&#39;PREFIX_*&#39;, count=100000):
print(key)
29. redis如何实现主从复制?以及数据同步机制?
https://blog.csdn.net/zhangguanghui002/article/details/
30. redis中的sentinel的作用?
帮助我们自动在主从之间进行切换
检测主从中 主是否挂掉,且超过一半的sentinel检测到挂了之后才进行进行切换。
如果主修复好了,再次启动时候,会变成从。
启动主redis:
redis-server /etc/redis-6379.conf
启动主redis
redis-server /etc/redis-6380.conf
启动从redis
在linux中:
找到 /etc/redis-sentinel-8001.conf
配置文件,在内部:
- 哨兵的端口 port = 8001
- 主redis的IP,哨兵个数的一半/1
找到 /etc/redis-sentinel-8002.conf
配置文件,在内部:
- 哨兵的端口 port = 8002
- 主redis的IP, 1
启动两个哨兵
31. 如何实现redis集群?
redis集群、分片、分布式redis
redis-py-cluster
集群方案:
- redis cluster 官方提供的集群方案。
- codis,豌豆荚技术团队。
- tweproxy,Twiter技术团队。
redis cluster的原理?
- 基于分片来完成。
- redis将所有能放置数据的地方创建了 16384 个哈希槽。
- 如果设置集群的话,就可以为每个实例分配哈希槽:
- 192.168.1.20【0-5000】
- 192.168.1.21【】
- 192.168.1.22【】
- 以后想要在redis中写值时,
set k1 123
将k1通过crc16的算法,将k1转换成一个数字。然后再将该数字和16384求余,如果得到的余数 3000,那么就将该值写入到 192.168.1.20 实例中。
32. redis中默认有多少个哈希槽?
33. 简述redis的有哪几种持久化策略及比较?
RDB:每隔一段时间对redis进行一次持久化。
- 缺点:数据不完整
- 优点:速度快
AOF:把所有命令保存起来,如果想到重新生成到redis,那么就要把命令重新执行一次。
- 缺点:速度慢,文件比较大
- 优点:数据完整
34. 列举redis支持的过期策略(数据淘汰策略)。
voltile-lru:
从已设置过期时间的数据集(server.db[i].expires)中挑选最近频率最少数据淘汰
volatile-ttl:
从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:
从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:
从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
35. MySQL 里有 2000w 数据,redis 中只存 20w 的数据,如何保证 redis 中都是热点数据?
相关知识:redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略(回收策略)。redis 提供 6种数据淘汰策略:
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
36. 写代码,基于redis的列表实现 先进先出、后进先出队列、优先级队列。
from scrapy.utils.reqser import request_to_dict, request_from_dict
from . import picklecompat
class Base(object):
&&&Per-spider base queue class&&&
def __init__(self, server, spider, key, serializer=None):
&&&Initialize per-spider redis queue.
Parameters
----------
server : StrictRedis
Redis client instance.
spider : Spider
Scrapy spider instance.
Redis key where to put and get messages.
serializer : object
Serializer object with ``loads`` and ``dumps`` methods.
if serializer is None:
# Backward compatibility.
# TODO: deprecate pickle.
serializer = picklecompat
if not hasattr(serializer, &#39;loads&#39;):
raise TypeError(&serializer does not implement &#39;loads&#39; function: %r&
% serializer)
if not hasattr(serializer, &#39;dumps&#39;):
raise TypeError(&serializer &#39;%s&#39; does not implement &#39;dumps&#39; function: %r&
% serializer)
self.server = server
self.spider = spider
self.key = key % {&#39;spider&#39;: spider.name}
self.serializer = serializer
def _encode_request(self, request):
&&&Encode a request object&&&
obj = request_to_dict(request, self.spider)
return self.serializer.dumps(obj)
def _decode_request(self, encoded_request):
&&&Decode an request previously encoded&&&
obj = self.serializer.loads(encoded_request)
return request_from_dict(obj, self.spider)
def __len__(self):
&&&Return the length of the queue&&&
raise NotImplementedError
def push(self, request):
&&&Push a request&&&
raise NotImplementedError
def pop(self, timeout=0):
&&&Pop a request&&&
raise NotImplementedError
def clear(self):
&&&Clear queue/stack&&&
self.server.delete(self.key)
class FifoQueue(Base):
&&&Per-spider FIFO queue&&&
def __len__(self):
&&&Return the length of the queue&&&
return self.server.llen(self.key)
def push(self, request):
&&&Push a request&&&
self.server.lpush(self.key, self._encode_request(request))
def pop(self, timeout=0):
&&&Pop a request&&&
if timeout & 0:
data = self.server.brpop(self.key, timeout)
if isinstance(data, tuple):
data = data[1]
data = self.server.rpop(self.key)
return self._decode_request(data)
class PriorityQueue(Base):
&&&Per-spider priority queue abstraction using redis&#39; sorted set&&&
def __len__(self):
&&&Return the length of the queue&&&
return self.server.zcard(self.key)
def push(self, request):
&&&Push a request&&&
data = self._encode_request(request)
score = -request.priority
# We don&#39;t use zadd method as the order of arguments change depending on
# whether the class is Redis or StrictRedis, and the option of using
# kwargs only accepts strings, not bytes.
self.server.execute_command(&#39;ZADD&#39;, self.key, score, data)
def pop(self, timeout=0):
Pop a request
timeout not support in this queue class
# use atomic range/remove using multi/exec
pipe = self.server.pipeline()
pipe.multi()
pipe.zrange(self.key, 0, 0).zremrangebyrank(self.key, 0, 0)
results, count = pipe.execute()
if results:
return self._decode_request(results[0])
class LifoQueue(Base):
&&&Per-spider LIFO queue.&&&
def __len__(self):
&&&Return the length of the stack&&&
return self.server.llen(self.key)
def push(self, request):
&&&Push a request&&&
self.server.lpush(self.key, self._encode_request(request))
def pop(self, timeout=0):
&&&Pop a request&&&
if timeout & 0:
data = self.server.blpop(self.key, timeout)
if isinstance(data, tuple):
data = data[1]
data = self.server.lpop(self.key)
return self._decode_request(data)
# TODO: Deprecate the use of these names.
SpiderQueue = FifoQueue
SpiderStack = LifoQueue
SpiderPriorityQueue = PriorityQueue
37. 如何基于redis实现消息队列?
不要使用redis去做消息队列,这不是redis的设计目标。
但实在太多人使用redis去做去消息队列,redis的作者看不下去,另外基于redis的核心代码,另外实现了一个消息队列disque:https://github.com/antirez/disque
38. 如何基于redis实现发布和订阅?以及发布订阅和消息队列的区别?
import redis
conn = redis.Redis(host=&#39;127.0.0.1&#39;,port=6379)
conn.publish(&#39;104.9MH&#39;, &hahaha&)
import redis
conn = redis.Redis(host=&#39;127.0.0.1&#39;,port=6379)
pub = conn.pubsub()
pub.subscribe(&#39;104.9MH&#39;)
while True:
msg= pub.parse_response()
print(msg)
39. 什么是codis及作用?
Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别 (不支持的命令列表), 上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务.
40. 什么是twemproxy及作用?
是 Twtter 开源的一个 Redis 和 Memcache 代理服务器,主要用于管理 Redis 和 Memcached 集群,减少与Cache 服务器直接连接的数量。
41. 写代码实现redis事务操作。
import redis
pool = redis.ConnectionPool(host=&#39;10.211.55.4&#39;, port=6379)
conn = redis.Redis(connection_pool=pool)
# pipe = r.pipeline(transaction=False)
pipe = conn.pipeline(transaction=True)
# 开始事务
pipe.multi()
pipe.set(&#39;name&#39;, &#39;bendere&#39;)
pipe.set(&#39;role&#39;, &#39;sb&#39;)
pipe.execute()
注意:咨询是否当前分布式redis是否支持事务
42. redis中的watch的命令的作用?
在Redis的事务中,WATCH命令可用于提供CAS(check-and-set)功能。假设我们通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃,同时返回Null multi-bulk应答以通知调用者事务执行失败。
面试题:你如何控制剩余的数量不会出问题?
- 通过redis的watch实现
import redis
conn = redis.Redis(host=&#39;127.0.0.1&#39;,port=6379)
# conn.set(&#39;count&#39;,1000)
val = conn.get(&#39;count&#39;)
print(val)
with conn.pipeline(transaction=True) as pipe:
# 先监视,自己的值没有被修改过
conn.watch(&#39;count&#39;)
# 事务开始
pipe.multi()
old_count = conn.get(&#39;count&#39;)
count = int(old_count)
print(&#39;现在剩余的商品有:%s&#39;,count)
input(&问媳妇让不让买?&)
pipe.set(&#39;count&#39;, count - 1)
# 执行,把所有命令一次性推送过去
pipe.execute()
- 数据库的锁
43. 基于redis如何实现商城商品数量计数器?
Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的10个用户–我们
称之为“user_scores”,我们只需要像下面一样执行即可:
当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一个很好的例子,用Ruby实}

我要回帖

更多关于 求下图阴影部分的面积 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信