首页 > 编程语言 > 详细

Python面试题

时间:2019-04-10 00:11:22      阅读:116      评论:0      收藏:0      [点我收藏+]

0、Python是什么

Python是一门:解释性、动态(无需声明变量类型)、强类型(字符串类型与整型不能比较)、完全面向对象语言。使用到Python的场景有:爬虫、Web 程序开发、桌面程序开发、科学计算、图像处理、人工智能等等。还包含八种数据类型:字符串、元组、字典、列表、集合、布尔类型、整型、浮点型。拥有三大特性:封装、继承、多态。最重要的特点是采用缩进/4个空格(不能混用)表示语句块的开始和结束。
标识符:Python区分大小写,可以由字母下划线数字组成,不能以数字开头,不能与关键字重名,不能含有特殊字符和空格,使用大驼峰、小驼峰式命名。
    _单下划线开头:声明为私有变量,通过from M import * 方式将不导入所有以下划线开头的对象,包括包、模块、成员。
    单下划线结尾_:为了避免与python关键字的命名冲突。
    __双下划线开头:模块内的成员,表示私有成员,外部无法直接调用
    __双下划线开头双下划线结尾__:指那些包含在用户无法控制的名字空间中的“魔术”对象或属性,如类成员的name 、doc、init、import、file、等。推荐永远不要将这样的命名方式应用于自己的变量或函数。
表达式:算术运算符  + - * / // %   ; 比较运算符 >  <  >=  <= !=  ; 逻辑运算符 and or not ;判断是否为同一对象:isis not   ;  判断是否属于另一个对象: innot in。
函数支持递归、默认参数值、可变参数、闭包,实参与形参之间的结合是传递对象的引用。
支持字典、集合、列表的推导式。
Python3中的print函数代替Python2的print语句
Python3中的Str类型代表Unicode字符串,Python2中的Str类型代表bytes字节序列
Python3中的 / 返回浮点数,Python2中根据结果而定,能被整除返回整数,否则返回浮点数
Python3中的捕获语法 except exc as var 代替Python2中的 except exc, var    

 

 

1、一行代码实现1--100之和

sum(range(101))

 

 

2、如何在一个函数内部修改全局变量  

a = 10    

def info():
  print(a)

def foo():
  global a
  a = 22
  print(a)

print(a)
info()
foo()

# 经过foo函数的修改,a的值已变为22
print(a)
info()

 

 

3、列出5个python标准库

sys、os、re、urllib、logging、datetime、random、threading、multiprocessing、base64

 

 

4、字典如何删除键和合并两个字典

di = {"name": "power"}
ci = {"age": 18}

# 删除键
del di["name"]

# 合并字典
di.update(ci)

 

 

5、python实现列表去重的方法

li = [2, 2, 1, 0, 0, 1, 2]

# 方法一:使用set方法
sl = list(set(li))


# 方法二:额外使用一个列表
li2 = list()
for i in li:
    if i not in li2:
        li2.append(i)
      

# 方法三:使用列表的sort方法
l1 = [b,c,d,c,a,a]
l2 = list(set(l1))
l2.sort(key=l1.index)
print(l2)

l1 = [b,c,d,c,a,a]
l2 = sorted(set(l1),key=l1.index)
print(l2)


 

 

6、一句话解释什么样的语言能够用装饰器?

函数可以作为参数传递的语言,就可以使用装饰器

 

 

7、python内建数据类型有哪些 

# 不可变类型
int      整形
str      字符串
float    浮点型
tuple  元组

bool   布尔型 

# 可变类型
list     列表
dict    字典
      

 

 

8、简述面向对象中__new__和__init__区别

1、__new__必须接收一个名为 cls 的参数,代表的是当前类对象。
2、__new__必须有返回值,返回的是由当前类对象创建的实例对象,而__init__什么都不返回。
3、__init__必须接收一个名为 self 的参数,代表的是由__new__方法所创建的实例对象。
4、只有在__new__方法返回一个 cls 的实例时,后面的__init__才能被调用。
5、当创建一个新实例对象是,自动调用__new__方法, 当初始化一个实例时调用__init__方法。

ps: __metaclass__ 是创建类时起作用.所以我们可以分别使用__metaclass__,__new____init__来分别在类创建,实例创建和实例初始化的时候做一些小手脚.

 

 

9、简述with方法打开处理文件帮我我们做了什么?

打开文件 ---> 写入数据  ---> 关闭文件
中间可能会出现异常, 还做了捕获异常操作

 

 

10、列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]

li = [1, 2, 3, 4, 5]

def info(x):
    return x**2

li2 = [i for i in map(info, li) if i > 10]

 

 

11、python中生成随机整数、随机小数、0--1之间小数方法

import random
import numpy as np

# 随机整数
print(random.randint(0, 99999))

# 随机小数
print(np.random.randn())

# 随机 0-1 小数
print(random.random())

 

 

12、避免转义给字符串加哪个字母表示原始字符串?

import re

a = power.top*one

res = re.match(r.*, a)

print(res)

# 注:r 只针对于Python代码生效,与re正则并无关系

 

 

13、<div class="nam">中国</div>,用正则匹配出标签里面的内容(“中国”),其中class的类名是不确定的

import re

a = <div class="nam">中国</div>

res = re.match(r<div class=".*">(.*)</div>, a)
res.group(1)


res = re.findall(r<div class=".*">(.*)</div>, a)
print(res[0])

 

 

14、python中断言方法举例

 技术分享图片

 

 

15、数据表student有id,name,score,city字段,其中name中的名字可有重复,需要消除重复行,请写sql语句

select distinct  name from student

 

 

16、10个Linux常用命令

cd、ls、cp、mv、mkdir、touch、cat、grep、echo、pwd、more、tar、tree

 

 

17、python2和python3区别? 

1、Python3 使用 print 必须要以小括号包裹打印内容,比如 print(hi)
   Python2 既可以使用带小括号的方式,也可以使用一个空格来分隔打印内容,比如 print hi

2、python3的range 返回可迭代对象,python2的range返回列表,xrange返回生成器
  for ... in 和 list() 都是迭代器

3、python2中使用ascii编码,python中使用utf-8编码

4、python2中unicode表示字符串序列,str表示字节序 python3中str表示字符串序列,byte表示字节序列

5、python2中为正常显示中文,引入coding声明,python3中不需要

6、python2中是raw_input()函数,python3中是input()函数

 


18、列出python中可变数据类型和不可变数据类型,并简述原理

可变类型: 列表、字典

不可变类型:字符串、整型、浮点型、元组

 


19、s = "ajldjlajfdljfddd",去重并从小到大排序输出"adfjl"

s = "ajldjlajfdljfddd"

# set方法
li = list(set(s))
li.sort()        # 注:sort 没有返回值


# 循环遍历
li2 = []
for i in s:
    if i not in li2:
        li2.append(i)
li2.sort()

 

20、用lambda函数实现两个数相乘

nu = lambda x, y: x*y

nu(2, 3)

 

21、字典根据键从小到大排序

dict(sorted(di.items(), key=lambda x: x))

 


22、利用collections库的Counter方法统计字符串每个单词出现的次数"kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h"

from collections import Counter

s = "kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h"
Counter(s)

# 输出结果
Counter({‘l‘: 9, ‘h‘: 6, ‘;‘: 6, ‘f‘: 5, ‘a‘: 4, ‘d‘: 3, ‘j‘: 3, ‘s‘: 2, ‘b‘: 1, ‘g‘: 1, ‘k‘: 1})

 

 

23、字符串a = "not 404 found 张三 99 深圳",每个词中间是空格,用正则过滤掉英文和数字,最终输出"张三  深圳

import re

a = "not 404 found 张三 99 深圳"

# 第一种方式
res = re.sub([^\u4e00-\u9fa5], ‘‘, a).split()
print(res)


# 第二种方式
value = re.findall(r[^a-zA-Z\d\s]+, a)
print(‘‘.join(value))

 

 

24、filter方法求出列表所有奇数并构造新列表,a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# filter(function, iterable)      function -- 判断函数。 iterable -- 可迭代对象。

a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


def info(x):
    
    if x % 2 == 1:
    
        return x


print(list(filter(info, a)))

 


25、列表推导式求列表所有奇数并构造新列表,a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

li = [i for i in a if i % 2 == 1]

 

 

26、正则re.complie作用

re.compile是将正则表达式编译成一个对象,加快速度,并重复使用

 

 

27、a=(1,)b=(1),c=("1") 分别是什么类型的数据?

元组 : a=(1,)

整型 :b=(1)

字符串 : c=("1")

 

 

28、两个列表合并为一个列表

#[1,2,5,6,7,8,9]

li1 = [1,5,7,9]
li2 = [2,2,6,8]

# 第一种方法
li3 = list(set(li1 + li2))
print(li3.sort())

# 第二种方法
li1.extent(li2)
li5 = list(set(li1))
li5.sort()
print(li5)

# 第三种方法
li6 = li1 + li2
print(li6)

 

 

29、用python删除文件和用linux命令删除文件方法

python:   os.remove(文件名)
linux:       rm  文件名

 

 

30、log日志中,我们需要用时间戳记录error,warning等的发生时间,请用datetime模块打印当前时间戳 “2018-04-01 11:38:54”

from datetime import datetime

print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

print(datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S"))


# Out[12]: 2019-03-30 18:57:55


logging模块的日志等级:

DEBUG    最详细的日志信息,典型应用场景是:问题诊断

INFO     信息细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作

WARNING   当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的

ERROR     由于一个更严重的问题导致某些功能不能正常运行时记录的信息

CRITICAL   当发生验证错误,导致应用程序不能继续运行时记录的信息

logging.debug(‘debug message‘)
logging.info(‘info message‘)
logging.warn(‘warn message‘)
logging.error(‘error message‘)
logging.critical(‘critical message‘)  

 

31、写一段自定义异常代码

li = [1, 2, 3, 0]

for i in li:
    try:
        if i == 0:
            raise Exception("遍历得到0")
    except Exception as e:
        print(e)

 

 

32、正则表达式匹配中,(.*)和(.*?)匹配区别?

(.*)是贪婪匹配,会把满足正则的尽可能多的往后匹配
(.*?)是非贪婪匹配,会把满足正则的尽可能少匹配

 

 

33、[[1,2],[3,4],[5,6]]一行代码展开该列表,得出[1,2,3,4,5,6]

li = [[1, 2], [3, 4], [5, 6]]

lis = [j for i in li for j in i]

 

 

34、x="abc",y="def",z=["d","e","f"],分别求出x.join(y)和x.join(z)返回的结果

x="abc"

z=["d","e","f"]

y="def"


x.join(y)
# Out[202]:‘dabceabcf‘

x.join(z)
# Out[202]: ‘dabceabcf‘

 

 

35、举例说明异常模块中 try except else finally 的相关意义

li = [1, 2, 3, 0]

for i in li:
    try:
         if i == 0:
             raise Exception("遍历得到0")
     except Exception as e:
         print(e)
     else:
         print(i)
     finally:
         print("顺利跑完")
 

# Out[28]:
1
顺利跑完
2
顺利跑完
3
顺利跑完
遍历得到0
顺利跑完


try: 放置可能出现异常的代码
except: 当出现异常时,执行此处代码
else: 当程序没有没有出现异常时,执行此处代码
finally:  不管程序是否出现异常,此处代码都会执行

 

 

36、举例说明zip()函数用法

技术分享图片

 

 

37、a="张明 98分",用re.sub,将98替换为100

res = re.sub(r\d+, 100, a)
print(res)

 

 

38、写5条常用sql语句

#
insert into student (name, age) values ("power", 22);

#
delete from student where name="power";

#
update student set age=12 where name="power";

#
select name from student where id=2;

 

 

39、简述ORM

O  模型类对象    R 关系    M 映射    :    模型类对象和数据库的表的映射关系


ORM拥有转换语法的能力,没有执行SQL 语句的能力,执行SQL语句需要安装数据库驱动(python3解释器需安装PyMySQL, python2解释器需安装mysql)django只能识别mysqldb驱动,需要给pymysql起别名骗过django

ORM作用:
1. 将面向对象的操作数据库的语法转换为相对应SQL语句
2. 解决数据库之间的语法差异性(根据数据库的配置不同,生成不同的SQL语句) 

 

 

40、a="hello"和b="你好"编码成bytes类型

a="hello"
print(ba)

b="你好"
print(b.encode())

 

  

41、提高python运行效率的方法

1、使用生成器,因为可以节约大量内存。 

2、循环代码的优化,避免重复执行循环代码。
 
3、核心模块用Cython  PyPy等,提高效率。
 
4、对于不同场景使用多进程、多线程、协程,充分利用CPU资源。
 
5、多个if elif条件判断,将最有可能先发生的条件放到前面写,可减少程序判断的次数。

 

 

42、遇到bug如何处理 

0、查看报错信息(错误日志信息),分析bug出现原因。

1、在接口的开头打断点,单步执行往下走,逐渐缩小造成bug的代码范围。

2、【可选】在程序中通过 print() 打印,能执行到print() 说明一般上面的代码没有问题,分段检测程序是否有问题,如果是js的话可以alert或console.log

2、若自己无法解决,利用搜索引擎将报错信息进行搜索。

3、查看官方文档,或者一些技术博客。

4、查看框架的源码。
5、对于bug进行管理与归类总结,一般测试将测试出的bug用teambin等bug管理工具进行记录。

 

 

43、正则匹配,匹配日期2018-03-20

a= aa20kk18-power03-30oo

res = re.findall(r[-\d]+, a)
data = ‘‘.join(res)
print(data)

Out[82]: 2018-03-30

 

 

44、list=[2,3,5,4,9,6],从小到大排序,不许用sort,输出[2,3,4,5,6,9]

li = [2, 3, 5, 4, 9, 6]
lis = []
# 冒泡排序
for i in range(len(l)-1): for j in range(len(l)-1): if l[j] > l[j+1]: l[j],l[j+1] = l[j+1], l[j] Out[51]: [2, 3, 4, 5, 6, 9]


# 递归删除
def info():
  nu = min(li)
  li.remove(nu)
  lis.append(nu)
  
  # 如果原列表中仍有数据,再次调用自身进行删除&追加
  if len(li)> 0:
    info()
  print(lis)

info()

 Out[77]: [2, 3, 4, 5, 6, 9]

 

 

45、写一个单例模式

# 第一种方法: 基类 __new__ 方法是真正创建实例对象的方法
class Info(object):
 def __new__(cls, *args, **kwargs):
        if not hasattr(cls, _instance):    
            cls._instance = super(Info, cls).__new__(cls, *args, **kwargs)
        return cls._instance


info = Info() 
info2
= Info()
print(id(foo), id(foo2))
#Out[106]: 140395100343696, 140395100343696


# 第二种方法 type元类是python创建类对象的类,类对象创建实例对象时必须调用 __call__方法
class Info(type):   
  def __call__(cls, *args, **kwargs):     
    
if not hasattr(cls, _instance):    
      #cls._instance = super().__call__(*args, **kwargs)   
      cls._instance
= super(Info, cls).__call__(*args, **kwargs)   
    
return cls._instance


class Foo(object):   
  __metaclass__ = Info


f
= Foo()
f1
= Foo()
print(id(f), id(f1))
#Out[
122]: 139622152568912, 139622152568912


单例模式应用场景:
资源共享的情况下,避免由于资源操作时导致的性能或损耗等,如日志文件,应用配置。
控制资源的情况下,方便资源之间的互相通信。如线程池等,1,网站的计数器 2,应用配置 3.多线程池 4数据库配置 数据库连接池 5.应用程序的日志应用...

 

46、保留两位小数

a = 0.255
b = 22

# 保留2位小数
print("%0.2f" % a)

# 补足6位
print("%06d" % b)

 

47、分别从前端、后端、数据库阐述web项目的性能优化 

前端内容优化:

(1)减少HTTP请求数:这条策略是最重要最有效的,因为一个完整的请求要经过DNS寻址,与服务器建立连接,发送数据,等待服务器响应,接收数据这样一个消耗时间成本和资源成本的复杂的过程。常见方法:合并多个CSS文件和js文件,利用CSS Sprites整合图像,Inline Images(使用 data:URL scheme在实际的页面嵌入图像数据 ),合理设置HTTP缓存等。
(2)减少DNS查找
(3)避免重定向
(4)使用Ajax缓存
(5)延迟加载组件,预加载组件
(6)减少DOM元素数量:页面中存在大量DOM元素,会导致javascript遍历DOM的效率变慢。
(7)最小化iframe的数量:iframes 提供了一个简单的方式把一个网站的内容嵌入到另一个网站中。但其创建速度比其他包括JavaScript和CSS的DOM元素的创建慢了1-2个数量级。
(8)避免404:HTTP请求时间消耗是很大的,因此使用HTTP请求来获得一个没有用处的响应(例如404没有找到页面)是完全没有必要的,它只会降低用户体验而不会有一点好处。



cookie优化:

(1)减小Cookie大小
(2)针对Web组件使用域名无关的Cookie



CSS优化:

(1)将CSS代码放在HTML页面的顶部
(2)避免使用CSS表达式
(3)使用<link>来代替@import
(4)避免使用Filters


JavaScript优化:

(1)将JavaScript脚本放在页面的底部。
(2)将JavaScript和CSS作为外部文件来引用:在实际应用中使用外部文件可以提高页面速度,因为JavaScript和CSS文件都能在浏览器中产生缓存。
(3)缩小JavaScript和CSS
(4)删除重复的脚本
(5)最小化DOM的访问:使用JavaScript访问DOM元素比较慢。
(6)开发智能的事件处理程序
(7)javascript代码注意:谨慎使用with,避免使用eval Function函数,减少作用域链查找。


HTML优化:

1、HTML标签有始终。 减少浏览器的判断时间

2、把script标签移到HTML文件末尾,因为JS会阻塞后面的页面的显示。

3、减少iframe的使用,因为iframe会增加一条http请求,阻止页面加载,即使内容为空,加载也需要时间

4、id和class,在能看明白的基础上,简化命名,在含有关键字的连接词中连接符号用‘-‘,不要用‘_‘

5、保持统一大小写,统一大小写有利于浏览器缓存,虽然浏览器不区分大小写,但是w3c标准为小写

6、清除空格,虽然空格有助于我们查看代码,但是每个空格相当于一个字符,空格越多,页面体积越大,像google、baidu等搜索引擎的首页去掉了所有可以去掉的空格、回车等字符,这样可以加快web页面的传输。可以借助于DW软件进行批量删除 html内标签之间空格,sublime text中ctrl+a,然后长按shift+tab全部左对齐,清除行开头的空格

7、减少不必要的嵌套,尽量扁平化,因为当浏览器编译器遇到一个标签时就开始寻找它的结束标签,直到它匹配上才能显示它的内容,所以当嵌套很多时打开页面就会特别慢。

8、减少注释,因为过多注释不光占用空间,如果里面有大量关键词会影响搜索引擎的搜索

9、使用css+div代替table布局,去掉格式化控制标签如:strong,b,i等,使用css控制

10、代码要结构化、语义化

11、css和javascript尽量全部分离到单独的文件中

12、除去无用的标签和空标签

13、尽量少使用废弃的标签,如b、i等,尽管高版本浏览器是向后兼容的



服务器优化:

(1)CDN:把网站内容分散到多个、处于不同地域位置的服务器上可以加快下载速度。
(2)GZIP压缩
(3)设置ETag:ETags(Entity tags,实体标签)是web服务器和浏览器用于判断浏览器缓存中的内容和服务器中的原始内容是否匹配的一种机制。
(4)提前刷新缓冲区

 
后端优化:

1.SQL优化,最常见的方式是,优化联表查询,以及优化索引。这里面包括,尽量使用left join 替代 where联表;当碰到,频繁查询字段A和字段B,以及AB联合查询的情况时,对AB做联合索引,能够有效的降低索引存储空间,提升查询效率。在复杂联表的情况下,可以考虑使用 Memory中间表。

2.主从数据库和读写分离,主从分库是用来应对访问量增加,带来频繁读写导致数据库的访问和操作性能下降的问题。对数据库的操作,为了保证数据的完整性,通常涉及到锁的机制的问题。MySQL的InnoDB引擎支持行级锁,而MyIsAM只支持表锁定。这样的话,如果读写集中在一个表中的情况下,当访问量增加,就会造成明显的性能下降。因此,通过主从数据库的方式可以实现读写分离。一般来说,使用InnoDB来作为写库,使用MyISAM作为读库。这种方式是缺点当然是,数据库的维护难度增加,但是通常都会有专门的DBA这个职位来负责。

3.数据库分库和分表.有的时候会出现,某个表变得越来越庞大,比如存放message信息表,这样会造成读取性能的增加。这种情况下,你可以通过分表的方式来解决。将一个大表切分成若干个表。

4.使用存储过程中,将一些操作,直接通过存储过程的方式,预先设置在MySQL,客户端只需要调用存储过程就可以操作数据。

5.对动态页面进行缓存,比如网站首页,内容页等这种查询次数高,数据改动不大的页面:应用程序读取数据时,先从缓存中读取,如果读取不到或数据已失效,再访问磁盘数据库,并将数据再次写入缓存。

  • 1)直接生成静态html页面,需要更新时通过后台成生成新页面进行覆盖。然后可以把静态页存放到本地硬盘或者同步到CDN上。
  • 2)使用vanish服务器作为方向代理,对php生成的动态页面进行缓存,由于vanish可以使用内存作为缓存,因此访问速度更快,且对生成页面的php代码不需要做任何的修改,就可以实现静态页面缓存。所以可以很好地解决因为一直遗留下来的问题导致代码修改成本高的情况。缺点也是,提升了运维成本。

6.浏览器缓存,通过Cache-Control,以及Last-Modified等控制缓存头的设置来告诉浏览器缓存页面。这样不必每次,都从服务器端重复请求新文件,也可以防止用户频繁刷新页面。

 

  代码优化:

  • 不断通过for循环去进行查找
  • 错误的选择了容器,导致不断的遍历查找
  • 在循环中添加了很多可以移到循环之外只运行一次的函数调用
  • 可以实现成 事件触发的逻辑 变成了轮询
  • 函数中存在大量重复调用
  • 避免循环和判断次数太多,如果多个if else判断,将最有可能先发生的情况优先判断
  • 将耗时操作放入celery异步任务中 

 

 

48、简述同源策略

协议相同: http / https
域名(主机号)相同
端口相同

 

 

49、简述cookie和session的区别 

Cookie:
cookie存储在客户端,不安全。
通过request对象获取cookie,通过response对象设置cookie。
cookie的设置和读取不能够同步进行,比如:第一次设置cookie时不能够立马获取。



Session:
session存储在服务器端(Redis数据库),获取&设置都通过request对象进行,安全。
session中多用于存储敏感、重要的信息,session依赖于cookie。


Session存储过程:
session通过request对象进行设置,假设将session数据(键值对)存储到数据库中,会生成一个session_id交由响应对象返回给浏览器,浏览器会将其保存在本地。
之后每一次请求这个网站时会自动携带session_id,服务器会根据session_id取出整条session数据。注意:session是依赖于cookie的,但是在浏览器中是可以禁用掉cookie的。
即:cookie被禁用,session也将失去意义,此条session记录在服务器中将不能取出。

 

 

50、简述any()和all()方法 

any():只要迭代器中有一个元素为真就为真

all():迭代器中所有的判断项返回都是真,结果才为真

Python中为假的条件:False、None、[]、()、{}、""、0

 

 

51、IOError、AttributeError、ImportError、IndentationError、IndexError、KeyError、SyntaxError、NameError分别代表什么异常

IOError:输入输出异常
AttributeError:试图访问一个对象没有的属性
ImportError:无法引入模块或包,基本是路径问题
IndentationError:语法错误,代码没有正确的对齐
IndexError:下标索引超出序列边界
KeyError:试图访问你字典里不存在的键
SyntaxError:Python代码逻辑语法出错,不能执行
NameError:使用一个还未赋予对象的变量

 

 

 

52、单位转换

    
    1 bytes = 8 bit
    1024 bytes = 1KB
    1024 KB = 1 MB
    1024 MB = 1 GB
    1024 GB = 1 TB
    1024 TB = 1 PB
    1024 PB = 1 EB
    1024 EB = 1 ZB

10进制,人类使用。
2进制, 供计算机使用,1,0代表开和关,有和无,机器只认识2进制。
16进制,内存地址空间是用16进制的数据表示, 如0x8049324。

十进制转二进制: 十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。

二进制转十进制: 把二进制数按权展开、相加即得十进制数。

二进制转八进制: 3位二进制数按权展开相加得到1位八进制数。(注意事项,3位二进制转成八进制是从右到左开始转换,不足时补0)。

八进制转成二进制: 八进制数通过除2取余法,得到二进制数,对每个八进制为3个二进制,不足时在最左边补零。

二进制转十六进制:与二进制转八进制方法近似,八进制是取三合一,十六进制是取四合一。(注意事项,4位二进制转成十六进制是从右到左开始转换,不足时补0)。

十六进制转二进制: 十六进制数通过除2取余法,得到二进制数,对每个十六进制为4个二进制,不足时在最左边补零。

十进制转八进制&十进制转十六进制:1.间接法—把十进制转成二进制,然后再由二进制转成八进制或者十六进制。  2.直接法—把十进制转八进制或者十六进制按照除8或者16取余,直到商为0为止。

八进制转十进制&十六进制转十进制:把八进制、十六进制数按权展开、相加即得十进制数。

八进制与十六进制之间的转换:1.先转成二进制然后再相互转换。  2.他们之间的转换可以先转成十进制然后再相互转换。

 

 

53、列出几种魔法方法并简要介绍用途

__new__(cls[, ...])       1.实例化对象时第一个被调用的方法     2.其参数直接传递给__init__方法处理

__init__(self[, ...])       构造方法,初始化类的时候被调用
__del__(self)            析构方法,当实例化对象被彻底销毁时被调用(实例化对象的所有指针都被销毁时被调用)
__call__(self[, args...])     允许一个类的实例像函数一样被调用:x(a, b) 调用 x.__call__(a, b)
__len__(self)            定义当被 len() 调用时的行为
__repr__(self)            定义当被 repr() 调用时的行为
__str__(self)            定义当被 str() 调用时的行为
__bytes__(self)           定义当被 bytes() 调用时的行为
__hash__(self)           定义当被 hash() 调用时的行为
__bool__(self)           定义当被 bool() 调用时的行为,应该返回 True 或 False
__format__(self, format_spec)        定义当被 format() 调用时的行为

 


54、a = "  hehheh  ",去除首尾空格

a.strip()
Out[95]: hehheh

 

 

 55、用两种方法去除空格

# 第一种方法:使用split方法分割
a =  hello world 
b = a.split()
c = ‘‘.join(b)
print(c)
#Out[22]:  ‘‘helloworld‘‘


# 第二种方法:使用re正则
a =  hello world 
b = re.sub( , ‘‘, a)
print(b)
#Out[23]:  ‘‘helloworld‘‘


# 第三种方法:使用strip方法去除首尾空格
a =  helloworld  
b = a.strip()
print(b)
#Out[24]:  ‘helloworld‘
# rstrip():去除尾部空格; lstrip():去除首部空格

 

 技术分享图片

 技术分享图片

 

 

56、举例sort和sorted对列表排序,list=[0,-1,3,-10,5,9]

li=[0,-1,3,-10,5,9]


li.sort()
print(li)
Out[90]: [-10, -1, 0, 3, 5, 9]


lis = sorted(li)
print(lis)
Out[90]: [-10, -1, 0, 3, 5, 9]

 

 

 57、对list排序foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4],使用lambda函数从小到大排序

foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4]

# 第一种方式
g = lambda x: x.sort()
g(foo)
print(foo)
# Out[102]: [-20, -5, -4, -4, -2, 0, 2, 4, 8, 8, 9]

# 第二种方式
a = sorted(foo, key=lambda x: x)
print(a)

 

 

58、使用lambda函数对list排序foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4],输出结果为[0,2,4,8,8,9,-2,-4,-4,-5,-20],正数从小到大,负数从大到小

foo = [-5, 8, 0, 4, 9, -4, -20, -2, 8, 2, -4]

g = sorted(foo, key=lambda x:(x<0, abs(x)))

print(g)

Out[113]: [0, 2, 4, 8, 8, 9, -2, -4, -4, -5, -20]

 

 

59、列表嵌套字典,根据年龄排序

alist = [{name:a,age:20},{name:b,age:30},{name:c,age:25}]

def sort_by_age(list1):
  
  return sorted(alist, key=lambda x:x[age], reverse=True)

 

 

60、以下代码的输出结果,为什么?

list = [a,b,c,d,e]
print(list[10:])


代码将输出[],不会产生IndexError错误,就像所期望的那样,尝试用超出成员的个数的index来获取某个列表的成员。例如,尝试获取list[10]和之后的成员,会导致IndexError。
然而,尝试获取列表的切片,开始的index超过了成员个数不会产生IndexError。

 

 

61、给定两个列表,怎么找出他们相同的元素和不同的元素?

A = [1,2,3]
B = [3,4,5]

A,B 中相同元素: print(set(A) & set(B))

A,B 中不同元素:  print(set(A) ^ set(B))

 

 

62、列表推导式、字典推导式、生成器

# 列表推导式
li = [i for i in range(1,101) if i % 2 ==0]

# 字典推导式
a = [0, 1, 2]
b = [a, b, c]
c = {a[i]:b[i] for i in range(len(a))}

# 生成器
def info(num):
  
  offset = 0
  a = 0
  b = 1

  while offset < num:
    result = a
    a, b = b, a+b
    offset += 1
    yield result

print(list(info(10)))   

 

 

63、正则匹配IPV4地址

IPV4由四组数字组成,中间由.隔开:

a = "169.254.0.112"
 re.search(r‘(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$‘, a).group()

 

 

64、举例说明SQL注入和解决办法

 

 

65、s="info:xiaoZhang 33 shandong",用正则切分字符串输出[‘info‘, ‘xiaoZhang‘, ‘33‘, ‘shandong‘]

s = info:xiaoZhang 33 shandong

# 正则方式
g = re.findall(r‘[^:\s]+‘, s)

 Out[162]: [‘info‘, ‘xiaoZhang‘, ‘33‘, ‘shandong‘]




# spilt分隔方式
li
= [] li.extend(s.split(":")[0].split() + s.split())

Out[156]: [info, xiaoZhang, 33, shandong]

 

 

66、正则匹配以163.com结尾的邮箱 

re.match(r[0-9a-zA-Z_]{0,19}@163.com, text).group()

 

 

67、递归求和 

def info(num):

    if num > 0:
        res = num + info(num - 1)
    else:
        res = 0
    return res


res = info(10)
print(res)

 

 

68、python字典和json字符串相互转化方法

json.dumps()   字典转json字符串
json.loads()     json转字典

 

 

69、快排

def info(li):
    
    midpivot = lil[0]
    lesspivot = [i for i in li[1:] if i <= midpivot]
    biggpivot = [i for i in li[1:] if i > midpivot]
    lesspivot.sort()
    biggpivot.sort()

    result = lesspivot + [midpivot] + biggpivot
    print(result)

 

 

 

70、RESTFul风格 

# 1、后端API定义规范
请求方法    请求地址    后端操作
GET            /goods    获取所有商品
POST    /goods    增加商品
GET            /goods/1    获取编号为1的商品
PUT            /goods/1    修改编号为1的商品
DELETE    /goods/1    删除编号为1的商品

# 2、尽量将API部署在专用域名之下。
https://api.example.com

# 将API的版本号放入URL。
http://www.example.com/app/2.0/foo

# 3、路径
资源作为网址,只能有名词,不能有动词,而且所用的名词往往与数据库的表名对应。
API中的名词应该使用复数。无论子资源或者所有资源。

# 4、错误处理
服务器向用户返回出错信息时,返回的信息以error作为键名,出错信息作为value值即可。

# 5、返回结果规范
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档

# 6、超媒体
访问api.github.com会得到一个所有可用API的网址列表。

# 7、服务器返回的数据格式应尽量为json格式,避免使用xml

 

 

71、列举3条以上PEP8编码规范

分号:不要在行尾加分号, 也不要用分号将两条命令放在同一行.

行长度:每行不超过80个字符

缩进:用4个空格来缩进代码,绝对不要用tab, 也不要tab和空格混用

空行:顶级定义之间空两行, 方法定义之间空一行

空格:按照标准的排版规范来使用标点两边的空格,括号内不要有空格,不要在逗号、分号、 冒号前面加空格, 但应该在它们后面加(除了在行尾),参数列表, 索引或切片的左括号前不应加空格.
导入格式:每个导入应该独占一行 
类:类应该在其定义下有一个用于描述该类的文档字符串. 如果你的类有公共属性(Attributes), 那么文档中应该有一个属性(Attributes)段. 并且应该遵守和函数参数相同的格式

继承:如果一个类不继承自其它类, 就显式的从object继承. 嵌套类也一样.

 

72、正则匹配中文

import re

title = "Hello World, 你好 世界"

pattern = re.compile(r[\u4e00-\u9fa5]+)
res = pattern.findall(title)

print(res)

 

 

73、Linux命令重定向 > 和 >>

 

Linux 允许将命令执行结果 重定向到一个 文件

将本应显示在终端上的内容 输出/追加 到指定文件中

> 表示输出,会覆盖文件原有的内容

>> 表示追加,会将内容追加到已有文件的末尾

 

 

74、正则表达式匹配出<html><h1>www.baidu.com</h1></html>

g = re.match(r<(\w+)><(\w+)>(.*)</\2></\1>, a)
g.group()

 

 

75、遍历列表的同时删除元素

# 1.新表用于遍历,旧表用于删除元素
a = [1, 2, 3, 4, 5, 6, 7, 8]
print(id(a))
print(id(a[:]))
for i in a[:]:
    if i>5:
        pass
    else:
        a.remove(i)
    print(a)
print(-----------)
print(id(a))


# 2.filter
a = [1, 2, 3, 4, 5, 6, 7, 8]
b = filter(lambda x: x>5, a)
print(list(b))


# 3.列表推导式
a = [1, 2, 3, 4, 5, 6, 7, 8]
b = [i  for i in a if i > 5]
print(b)


# 4.倒序删除
a = [1, 2, 3, 4, 5, 6, 7, 8]
print(id(a))
for i in range(len(a)-1,-1,-1):
    if a[i]>5:
        pass
    else:
        a.remove(a[i])

print(id(a))
print(-----------)
print(a)

 

 

 

76、常见的网络传输协议

HTTP(80)      浏览器的网络请求 协议
HTTPS(443)    浏览器的网络请求 协议
TCP        数据传输协议
UDP        数据传输协议
SMTP(25)    发邮件协议    
TEL      电话协议  
SMS     短信协议     
POP3    收邮件协议 (需经过邮件服务器,从服务器拉去最新邮件时,服务器不做缓存) 
IMAP    收邮件协议(即使本地邮件删除,服务器上还有备份的邮件) 
HHT     文件传输协议 

 

 

77、8个老师随机分配3个办公室, 每个办公室人数在2~3人

 

 

78、静态函数、类函数、成员函数的区别

类方法: 是类对象的方法,在定义时需要在上方使用 @classmethod 进行装饰,形参为cls,表示类对象,类对象和实例对象都可调用

类实例方法: 是类实例化对象的方法,只有实例对象可以调用,形参为self,指代对象本身;

静态方法: 是一个任意函数,在其上方使用 @staticmethod 进行装饰,可以用对象直接调用,静态方法实际上跟该类没有太大关系

\实例方法类方法静态方法
a = A() a.foo(x) a.class_foo(x) a.static_foo(x)
A 不可用 A.class_foo(x) A.static_foo(x)

 

 

79、变量查找顺序

L: local 函数内部作用域(本地作用域)

E: enclosing 函数内部与内嵌函数之间

G: global 全局/模块作用域

B: build-in 内置作用域

 

 

79.字符串 "123" 转换成 123,不使用内置api,例如 int()

# 方法一:利用 str方法
def atoi(s):
    num = 0
    for v in s:
        for j in range(10):
            if v == str(j):
                num = num * 10 + j
    return num


# 方法二:利用 ord方法
def atoi(s):
    num = 0
    for v in s:
        num = num * 10 + ord(v) - ord(0)
    return num


# 方法三:利用 eval方法
def atoi(s):
    num = 0
    for v in s:
        t = "%s * 1" % v
        n = eval(t)
        num = num * 10 + n
    return num


# 方法四:使用 reduce 并结合方法二
from functools import reduce
def atoi(s):
    return reduce(lambda num, v: num * 10 + ord(v) - ord(0), s, 0)

 

 

80、MySQL的事务隔离级别

未提交读(Read Uncommitted):允许脏读,其他事务只要修改了数据,即使未提交,本事务也能看到修改后的数据值。也就是可能读取到其他会话中未提交事务修改的数据
提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)。
可重复读(Repeated Read):可重复读。无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响。
串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

MySQL数据库(InnoDB引擎)默认使用可重复读( Repeatable read)


命令行修改数据库事务隔离级别:transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}
配置文件中修改数据库事务隔离级别(最后一行进行添加):transaction-isolation={READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}

===============================================================================================================
       隔离级别               脏读(Dirty Read)          不可重复读(NonRepeatable Read)     幻读(Phantom Read) 
===============================================================================================================

未提交读(Read uncommitted)        可能                            可能                      可能

已提交读(Read committed)          不可能                          可能                       可能

可重复读(Repeatable read)         不可能                          不可能                     可能

可串行化(Serializable )           不可能                          不可能                     不可能

===============================================================================================================

 

脏读: 脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

栗子: 1.Mary的原工资为1000, 财务人员将Mary的工资改为了8000(但未提交事务)
      2.Mary读取自己的工资 ,发现自己的工资变为了8000,欢天喜地!
      3.而财务发现操作有误,回滚了事务,Mary的工资又变为了1000
          像这样,Mary记取的工资数8000是一个脏数据。

 

不可重复读 :是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。

栗子1.在事务1中,Mary 读取了自己的工资为1000,操作并没有完成

     2.在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务.
     3.在事务1中,Mary 再次读取自己的工资时,工资变为了2000

解决办法:如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。

 

幻读: 是指当事务不是独立执行时发生的一种现象,比如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么就会发生,操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

 

栗子:目前工资为1000的员工有10人。
     1.事务1,读取所有工资为1000的员工。
     2.这时事务2向employee表插入了一条员工记录,工资也为1000
    3.事务1再次读取所有工资为1000的员工 共读取到了11条记录, 
解决办法:如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据,则可避免该问题

 

丢失更新:两个事务同时更新一行数据,最后一个事务的更新会覆盖掉第一个事务的更新,从而导致第一个事务更新的数据丢失,这是由于没有加锁造成的;

 

 

81、TCP协议的 TIME WAITE 状态

# 1.TIME WAITE状态:
是指主动关闭方在发送四次挥手的最后一个ACK后会进入TIME_WAIT状态,也就是这个发起关闭的一方会保持2MSL时间之后才会回到初始状态。(linux里一个MSL为30s,是不可配置的)

# 2.MSL值是数据包在网络中的最大生存时间。当主动关闭方进入TIME WAITE状态后,会使得这个TCP连接在2MSL连接等待期间,定义这个连接的四元数组(local_ip, local_port, remote_ip,remote_port)不能被使用。

# 3.TIME_WAIT状态产生的原因:
虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到
假设发起主动关闭的一方(client)四次挥手时最后发送的ACK在网络中丢失,但由于TCP协议的重传机制,执行被动关闭的一方(server)将会重发上一个数据包FIN,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。(TCP属于全双工连接)
# 4.TIME_WAIT两个MSL的作用: 可靠安全的关闭TCP连接。比如网络拥塞,主动方最后一个ACK被动方没收到,这时被动方会对FIN开启TCP重传,发送多个FIN包,在这时尚未关闭的TIME_WAIT就会把这些尾巴问题处理掉,不至于对新连接及其它服务产生影响。 # 5.TIME_WAIT状态如何避免(端口复用): 如果服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,可以通过(SO_REUSEADDR, True)选项避免TIME_WAIT状态。

 

 

82、网络的七层协议

OSI的7层从上到下分别是:
  7 应用层 6 表示层 5 会话层 4 传输层 3 网络层 2 数据链路层 1 物理层 
  其中高层(即7、6、5、4层)定义了应用程序的功能,下面3层(即3、2、1层)主要面向通过网络的端到端的数据流。

应用层:与其它计算机进行通讯的一个应用,它是对应应用程序的通信服务的。TELNET,HTTP,FTP,NFS,SMTP

表示层:定义数据格式及加密。加密,ASCII等。

会话层:定义了如何开始、控制和结束一个会话,包括对多个双向消息的控制和管理,以便在只完成连续消息的一部分时可以通知应用,表示层看到的数据是连续的,本质用于区分不同进程的。RPC,SQL等。

传输层:负责将数据进行可靠或者不可靠传递,负责终端之间的传送。即:选择差错恢复协议还是无差错恢复协议,以及在同一主机上对不同应用的数据流输入进行复用,还包括对收到顺序不对的数据包的重新排序功能。TCP,UDP,SPX。

网络层:负责选择最佳路径,并保证数据始终沿着最佳路径传输,以数据包为单位。IP,IPX等。

数据链路层:在单个链路上如何传输数据,比如对数据进行处理封装成数据帧,进行传递和错误检测的就是数据链路层,数据以帧为单位。ATM,FDDI等。

物理层:为网络设备之间的数据通信提供传输媒体及互连设备,为数据传输提供可靠的环境,数据是以比特的形式传递的。Rj45,802.3等。


栗子:从西班牙去罗马的贸易商人
1、 要想贸易获得成功,首先要有至少一条路,能够从西班牙通向罗马。此层为【物理层】
2、有了路是不是就能去贸易了?还要保证路上不会把商人的货物给磕坏了,要有一层保护的包装。引出第二层,【数据链路层】
3、所谓条条道路通罗马。并不只有一条路能够到达罗马,那么在那么多的选择中选一条最短的,或者路费的成本最少的,这才符合商人的利益。引出第三层,【网络层】以上三层为网络中的下三层,叫媒体层,让我们来看看另外4层。
4、贸易出门前要先检查一下自己的货,有没有拿错了,事先要检查过,如果错了要重新取货,引出第四层,【传输层】。
5、是不是可以上路了?还不行。我们要和罗马联系好, 如果我们这边的货物到了那边卖不出去怎么办?我们首先要交流、协商一下,看看罗马的市场情况,能和那边的另外一个商人合作的话就更好了,这就需要一些外交的关系。叫做【会话层】。
6、好象所有的事情都准备好了,但是商人到了罗马以后突然发现,他的商队里没有人能听懂罗马人的话,罗马人也没有人能听懂西班牙语,这个时候,还需要一个翻译,要么把两种语言都转换成一种国际通用语言,比如说英语,要么至少能让双方能交流。这里就是【表示层】。
7、到了罗马了,最终需要在交易所中把商品卖掉,这个交易所就是一个交易平台,相当于各个软件平台,引出最后一层,【应用层】。

 

 

83、HTTP和TCP的keep-alive区别

1、keep-alive(持久连接/长连接):Http是一个请求-响应协议,它的keep-alive主要是为了使用同一个TCP连接来发送和接收多个HTTP请求/应答,而不是为每一个新的请求/应答打开新的连接的方法。可以减少tcp连接建立次数,也意味着可以减少TIME_WAIT状态连接,以此提高性能(更少的tcp连接意味着更少的系统内核调用,socket的accept()和close()调用)。

2、HTTP的keep-alive:   HTTP 1.0版本中默认没有keep-alive操作,是根据浏览器是否支持keep-alive而决定的,如果浏览器支持的话,它会在请求报头中添加 Connection: Keep-Alive 字段,而服务器做出响应时也会在响应报头中添加 Connection: Keep-Alive,这样就会保持当前的连接而不会中断。HTTP 1.1版本中默认所有都是持久连接。 需要特别注意的是:长时间的tcp连接容易导致系统资源无效占用。配置不当的keep-alive,有时比重复利用连接带来的损失还更大。所以,正确地设置keep-alive timeout时间非常重要。keep alive_timout时间值意味着:一个http产生的tcp连接在传送完最后一个响应后,还需要hold住keep alive_timeout秒后,才开始关闭这个连接。 3、TCP的keep-alive:
Tcp的keep-alive是Tcp协议的一种保鲜装置,当链接建立之后,如果应用程序或者上层协议一直不发送数据,或者隔很长时间才发送一次数据的情况下,TCP协议需要考虑当链接很久没有数据报文传输时确定对方是否还在线,到底是掉线了还是确实没有数据传输,链接还需不需要保持。在此情况下,当超过一段时间之后,
服务器自动发送一个监测包(数据为空的报文)
如果对方回应了这个报文,说明对方还在线,链接可以继续保持,如果对方没有报文返回,并且重试了多次之后则认为链接丢失,没有必要保持链接。


4、http keep-alive与tcp keep-alive: http keep-alive是为了让tcp活得更久一点,以便在同一个连接上传送多个http,提高socket的效率。而tcp keep-alive是TCP的一种检测TCP连接状况的机制。
tcp keepalive原理,当网络两端建立了TCP连接,但双方没有任何数据流发送往来,服务器内核就会尝试向客户端发送侦测包,来判断TCP连接状况(有可能客户端崩溃、强制关闭了应用、主机不可达等等)。如果没有收到对方的回答(ack包),则会在指定x时间后再次尝试发送侦测包,直到收到对方的ack包,如果一直没有收到对方的ack,一共会尝试y次数。如果重试y次数后,依然没有收到对方的ack包,则会丢弃该TCP连接。

 

 

84、当保持长连接时,如何判断一次请求已经完成? 

Content-Length 
Content-Length表示实体内容的长度。浏览器通过这个字段来判断当前请求的数据是否已经全部接收。 所以,当浏览器请求的是一个静态资源时,即服务器能明确知道返回内容的长度时,可以设置Content-Length来控制请求的结束。
但当服务器并不知道请求结果的长度时,如一个动态的页面或者数据,Content-Length就无法解决上面的问题,这个时候就需要用到Transfer-Encoding字段。 Transfer-Encoding Transfer-Encoding是指传输编码,在上面的问题中,当服务端无法知道实体内容的长度时,就可以通过指定Transfer-Encoding: chunked来告知浏览器当前的编码是将数据分成一块一块传递的。
当然, 还可以指定Transfer-Encoding: gzip, chunked表明实体内容不仅是gzip压缩的,还是分块传递的。最后,当浏览器接收到一个长度为0的chunked时, 知道当前请求内容已全部接收。

 

 

85、TCP&UDP的区别

TCP :
是一种面向连接的、可靠的字节流服务,一个客户端和一个服务器在发送数据之前必须先三次握手建立连接。 在一个 TCP 连接中,仅有两方进行彼此通信。广播和多播不能用于 TCP。
TCP 采用发送应答机制,所发送的每个报文段都必须得到接收方的应答才认为这个TCP报文段传输成功。
TCP 协议的超时重传机制,发送一个报文段后就启动定时器,若在一定时间内未收到对方应答就会重新发送这个报文段。
TCP 为了保证不发生丢包,会给每一个包标上序号,也保证了消息的有序性。该消息从服务器端发出顺序会以同样的顺序发送到客户端。
因为TCP必须创建连接,以保证消息的可靠交付和有序性,所以相对于UDP而言TCP速度比较慢。
TCP 数据包报头的大小是20字节,UDP数据报报头是8个字节。TCP报头中包含序列号,ACK号,数据偏移量,保留,控制位,窗口,紧急指针,可选项,填充项,校验位,源端口和目的端口。而UDP报头只包含长度,源端口号,目的端口,和校验和。
TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制,以此避免主机发送得过快而使接收方来不及完全收下。
TCP 用?个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
TCP 使用发送应答机制、超时重传、错误校验、流控和阻塞管理来保证可靠传输。
注意:TCP 并不能保证数据一定会被对方接收到,因为这是不可能的。TCP 能够做到的是,如果有可能,就把数据递送到接收方;否则就(通过放弃重传并且中断连接这一手段)通知用户。因此准确说 TCP 也不是 100% 可靠的协议,它所能提供的是数据的可靠递送或故障的可靠通知。

UDP :
是无连接的,不可靠的,没有序列保证,但是一个快速传输的数据报协议。
UDP 缺乏可靠性。UDP 本身不提供确认,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次
UDP 数据报是有长度的。每个 UDP 数据报都有长度,如果一个数据报正确地到达目的地,那么该数据报的长度将随数据一起传递给接收方。而 TCP 是一个字节流协议,没有任何(协议上的)记录边界。
UDP 是无连接的。UDP 客户和服务器之前不必存在长期的关系。UDP 发送数据报之前也不需要经过握手创建连接的过程。
UDP 支持多播和广播。

 

 86、闭包是什么?

闭包必须满足的三个条件:
1、必须有一个内嵌函数
2、内嵌函数必须引用外部函数中的变量
3、外部函数的返回值必须是内嵌函数

 

 

87、中间件是什么?

在django中,中间件其实就是一个类,监听请求进入视图之前 响应对象真正到达浏览器之前的中间执行过程,django会根据自己的规则在合适的时机执行中间件中相应的方法。在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件
中间件中一共有四个方法:
__init__     # 初始化:无需任何参数,服务器响应第一个请求的时候调用一次,用于确定是否启用当前中间件

process_request(request)    # 处理请求前:在每个请求上调用,返回None或HttpResponse对象。 

process_view(request,view_func,view_args,view_kwargs)      # 处理视图前:在每个请求上调用,返回None或HttpResponse对象。
process_template_response(request,response)  # 处理模板响应前:在每个请求上调用,返回实现了render方法的响应对象。
process_exception(request,exception)  # 当视图抛出异常时调用,在每个请求上调用,返回一个HttpResponse对象。 process_response(request,response)  # 处理响应后:所有响应返回浏览器之前被调用,在每个请求上调用,返回HttpResponse对象。 Django自定义中间件类时,必须继承自MiddlewareMixin父类:from django.utils.deprecation import MiddlewareMixin
Flask中的请求钩子也类似于中间件,通过装饰器实现的,支持以下四种: before_first_request:第一次请求之前,可以在此方法内部做一些初始化操作。 before_request:每次请求之前,可以对不同请求的url处理不同的业务逻辑。 after_request:每次请求之后,可以使用response对象统一设置cookie。 teardown_request:每次请求之后是否有错误,会接受一个参数,参数是服务器出现的错误信息。

 

 

 

88、深浅拷贝

1、复制不可变数据类型,不管copy还是deepcopy,都是同一个地址当浅复制的值是不可变对象(数值,字符串,元组)时和=“赋值”的情况一样,对象的id值与浅复制原来的值相同。

2、复制的值是可变对象(列表和字典)

浅拷贝copy有两种情况:

第一种情况:复制的 对象中无 复杂 子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。

第二种情况:复制的对象中有 复杂 子对象 (例如列表中的一个子元素是一个列表), 改变原来的值 中的复杂子对象的值  ,会影响浅复制的值。

深拷贝deepcopy:完全复制独立,包括内层列表和字典

 

 

89、Redis缓存击穿、缓存穿透、缓存雪崩

缓存穿透
概念:缓存穿透是指查询一个一定不存在的数据,由于缓存是请求数据不命中时被动写入的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,在流量大时数据库可能就挂掉了,通俗说就是恶意用户模拟请求很多缓存中不存在的数据,由于缓存中都没有,导致这些请求短时间内直接落在了数据库上,导致数据库异常。从系统层面来看像是穿透了缓存层直接达到db。
解决:
布隆过滤器(bloom filter):类似于哈希表的一种算法,将所有可能存在的数据哈希到一个足够大的bitmap中,在进行数据库查询之前会使用这个bitmap进行过滤,如果一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
空值缓存:一种比较简单的解决办法,在第一次查询完不存在的数据后,将该key与对应的空值也放入缓存中,只不过设定为较短的失效时间,最长不超过五分钟。,这样则可以应对短时间的大量的该key攻击,设置为较短的失效时间是因为该值可能业务无关,存在意义不大,且该次的查询也未必是攻击者发起,无过久存储的必要,故可以早点失效。



缓存雪崩
概念:缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。
解决:
线程互斥:只让一个线程构建缓存,其他线程等待构建缓存的线程执行完,重新从缓存获取数据才可以,每个时刻只有一个线程在执行请求,减轻了db的压力,但缺点也很明显,降低了系统的qps。
交错失效时间:可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。



缓存击穿
概念:对于一些设置了过期时间的key,如果这些key在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候可能会发生缓存被“击穿”的问题,和缓存雪崩的区别在于:缓存击穿是针对某一/几个key缓存,缓存雪崩则是很多key。当缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
比如:微博有一个热门话题的功能,用户对于热门话题的搜索量往往在一些时刻会大大的高于其他话题,这种我们成为系统的“热点“,由于系统中对这些热点的数据缓存也存在失效时间,在热点的缓存到达失效时间时,此时可能依然会有大量的请求到达系统,没有了缓存层的保护,这些请求同样的会到达db从而可能引起故障。击穿与雪崩的区别即在于击穿是对于特定的热点数据来说,而雪崩是全部数据。
解决:
二级缓存:对于热点数据进行二级缓存,并对于不同级别的缓存设定不同的失效时间,则请求不会直接击穿缓存层到达数据库。
互斥锁(mutex key): 只让一个线程构建缓存,其他线程等待构建缓存的线程执行完,重新从缓存获取数据即可。
LRU算法:根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。最常见的实现是使用一个链表保存缓存数据,缓存步骤:
    首先将新数据放入链表的头部
    在进行数据插入的过程中,如果检测到链表中有数据被再次访问也就是有请求再次访问这些数据,那么就其插入的链表的头部,因为它们相对其他数据来说可能是热点数据,具有保留时间更久的意义
    最后当链表数据放满时将底部的数据淘汰,也就是不常访问的数据

 

 

90、实现WSGI协议的框架

WSGI协议:必须同时实现 web server 和 web application;WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web server如何与web application通信的规范。
WSGI协议其实是定义了一种server与application解耦的规范,即可以有多个实现WSGI server的服务器,也可以有多个实现WSGI application的框架,可以选择任意的server和application组合实现自己的web应用。例如uWSGI和Gunicorn都是实现了WSGI server协议的服务器,Django,Flask是实现了WSGI application协议的web框架,可以根据项目实际情况搭配使用。
WSGI server:负责从客户端接收http请求,将request转发给WSGI application,将application返回的response返回给客户端 WSGI application:接收由server转发的request,并处理请求,最后将response处理结果返回给server。 application中可以包括多个栈式的中间件(middlewares),这些中间件需要同时实现server与application,可以在WSGI服务器与WSGI应用之间起调节作用:对服务器来说,中间件扮演应用程序,对应用程序来说,中间件扮演服务器。
WSGI application应该实现为一个可调用对象,例如函数、方法、类(包含`call`方法)。需要接收两个参数:1、一个字典,该字典可以包含了客户端请求的信息以及其他信息,可以认为是请求上下文,一般叫做environment(编码中多简写为environ、env) 2、一个用于发送HTTP响应状态(HTTP status )、响应头(HTTP headers)的回调函数 通过回调函数将响应状态和响应头返回给server,同时返回响应正文(response body),响应正文是可迭代的、并包含了多个字符串。
uwsgi:与WSGI一样是一种通信协议,是uWSGI服务器的独占协议,用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型的描述。 
uWSGI:是一个web服务器,实现了WSGI协议、uwsgi协议、http协议等。主要特点:超快的性能,低内存占用,多app管理,详尽的日志功能(可以用来分析app的性能和瓶颈),高度可定制(内存大小限制,服务一定次数后重启等)
生产环境使用的WSGI服务器: gunicorn:接受从Nginx转发的动态请求,处理完之后返回给Nginx,由Nginx返回给用户。 uwsgi:把HTTP协议转化成语言支持的网络协议。比如把HTTP协议转化成WSGI协议,让Python可以直接使用。 注:响应时间较短的应用中,使用uWSGI+django;如果有部分阻塞请求 Gunicorn+gevent+django有非常好的效率; 如果阻塞请求比较多的话,还是用tornado重写吧。

 

 

91、简述Django的MVT模式

### MVC: 浏览器 --> Controll

Model : 用于 `Controll(服务器)和数据库的交互`,对数据库中的数据进行增、删、改、查操作。

View : 用于`封装html,css,js`,生成页面展示的html内容(数据的呈现方式)。

Controll : 用于 `接收请求,业务处理,返回结果`  & `C和V交互、C和M交互、C和客户端交互`

C必不可缺



### MVT:浏览器 --> 路由器 --> View(MVC中的C) 

M : model  `View (服务器)和数据库的交互`

V : View 等同于 `MVC的Controll`,接收请求,业务处理,返回结果 & C和V交互 、C和M交互 、C和客户端交互

T : template  `封装html,css,js`,负责封装构造要返回的html(如何显示数据,产生html界面)。

V必不可缺

 

 

92、python常用的第三方库

requests、Scrapy、threading、multiprocessing、gevent、pygame、pymysql、pymongo、redis-py、Django、Flask、Werkzeug、celery、IPython、pillow

 

93、实现斐波那契数列

# 1、生成器方式
def fibonacci(num):

    a = 0
    b = 1
    offset = 0

    while offset < num:
        result = a
        a, b = b, a+b
        offset += 1

        yield result


result = fibonacci(10)
for i in result:
    print(i)



# 2、迭代器方式

class Fibonacci(object):
    """
    斐波那契数列 : 第一个数为 0 , 第二个数为 1 ,其后的每一个数都由前两数相加之和
    """

    def __init__(self, num):

        self.offset = 0  # 记录当前取值的位置
        self.a = 0
        self.b = 1
        self.num = num  # 指定最终输出数列的长度

    def __iter__(self):

        return self  # 返回自身,自身就是一个迭代器

    def __next__(self):

        if self.offset < self.num:
            result = self.a
            self.a, self.b = self.b, self.a + self.b
            self.offset += 1
            return result
        else:
            raise StopIteration  # 抛出异常,停止迭代


list1 = list(Fibonacci(10))  # 也可使用 元组,列表..接收结果
print(list1)

 

 

94、输入某年某月某日,判断今日是当年的第几天?

import datetime

y = int(input("请输入4位数字的年份:"))
m = int(input("请输入月份:"))
d = int(input("请输入是哪一天"))

targetDay = datetime.date(y,m,d)
dayCount = targetDay - datetime.date(targetDay.year -1,12,31)
print("%s是 %s年的第%s天。"%(targetDay,y,dayCount.days))

 

 

95、什么是猴子补丁?

在运行期间动态修改一个类或模块(在函数或对象已经定义之后,再去改变它们的行为)

 

except exc as var

Python面试题

原文:https://www.cnblogs.com/hsmwlyl/p/10624875.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!