用于python面试整理,主要来源于http://www.cnblogs.com/skiler/p/6952707.html,很感谢博主分享,欢迎指正交流。
Python面试200题(含爬虫)
面试题(一)【15】
1、现有两元祖 (('a'),('b'),('c'),('d') ) ,请使用Python中的匿名函数生成列表[ {'a':'c',{'c':'d'}]
答案:v = list(map(lambda x,y:{x:y},data[0:2],data[2:4]))
data = (('a'),('b'),('c'),('d') )
v = list(map(lambda x,y:{x:y},data[0:2],data[2:4]))
data[0:2] = ('a'),('b')
data[2:4] = ('c'),('d')
匿名函数传进去 参数(x,y) 返回{x:y}
map(func,iterable) #对于iterable依次传递给func,返回的是可迭代对象
2、看代码 写结果
def multipliters():
return [lambda x:i * x for i in range(4)]
print([m(2) for m in multipliters()])
# 第一种是 将生成器对象生成的匿名函数转化成列表 ,匿名函数使用的是相同的内存空间。
# 转换成列表后,循环结束,命名空间里的i都为3
def multipliters():
return [lambda x:i * x for i in range(4)]
print([m(2) for m in multipliters()])
# 以下是依次返回 生成器生成的每个匿名函数,每次调用i都在变化
def multipliters2():
return (lambda x: i*x for i in range(4))
print([m(2) for m in multipliters2()])
3、1 or 2和1 and 2分别输出什么?
# 1 2
# 0 "" [] {} set() None False放入判断表达式都为假
# or或 and与
# 整个式子 不断去向右查看,直到能确定为真就停下来
4、看代码 写结果
value = "B" and "A" or "C"
print(value)
# A
# 整个式子 不断去向右查看,直到能确定为真就停下来
5、看代码写结果
v1 = [i % 2 for i in range(10)]
v2 = (i % 2 for i in range(10))
print(v1,v2)
# v1 = [i % 2 for i in range(10)]为列表生成式
# v2 = (i % 2 for i in range(10))为 at 0x00E4F990>为生成式
6、看代码,写结果
def extendList(val,li=[]):
li.append(val)
return li
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
print(list1)
print(list2)
print(list3)
# [10, 'a']
# [123]
# [10, 'a']
# 参数变量在编译会生成,而且只会生成一次,其内存地址的指向不发生变化
# 所以会有默认的 []
# 1、3都会使用默认的 编译生成同一个[]
# 2新生成一个[]
7、下面代码谁报错?
v1 = {}
v2 = {3:5}
v3 = {[11,23]:5}
v4 = {(11,23):5}
v3错误,字典元素的键不能为可变对象
8、输出以下结果
for i in range(5,0,1):
print(i)
# range(起始元素,结束元素(不包含),每次的变化)
# 5 每次加1,啥时候能加到0,O(∩_∩)O哈哈~
9、请说出range和xrange的区别
# from collections import Iterable,Iterator
# Iterable可迭代对象
# Iterator迭代器
# print(isinstance(xrange(10),Iterator))
# print(isinstance(xrange(10),Iterable))
# python2中range(start, stop[, step])和range(stop)会生成-> range object,,返回是列表,是可迭代对象,全部放在内存里
# python2中xrange(start, stop[, step])和range(stop)会生成-> xrange object,返回是可迭代对象,每次调用时才会生成
# python3 没有xrange,只有range,也是可迭代对象,每次调用时才会生成
10、请将"1,2,3",变成["1","2","3"]
"1,2,3".split(',')
11、一行代码生成[1,4,9,16,25,36,49,64,81,100]
[i*i for i in range(11)]
12、一行生成9 * 9乘法表
[ x for x in range(1,10)]
[ x*y for y in range(1,x+1)]
[ ([ x*y for y in range(1,x+1)]) for x in range(1,10)]
[ ([ '{}*{} = {}'.format(x,y,x*y) for y in range(1,x+1)]) for x in range(1,10)]
'\n'.join([ str(x) for x in range(1,10)])
print('\n'.join([ ' '.join( [ '{}*{} = {}'.format(x,y,x*y) for y in range(1,x+1)] ) for x in range(1,10)]) )
13、map(str,[1,2,3,4,5,6,7,8,9])输出什么?Python2和Python3输出的结果一样吗?
print(isinstance(map(str,[1,2,3,4,5,6,7,8,9]),Iterable))
print(isinstance(map(str,[1,2,3,4,5,6,7,8,9]),Iterator))
# python 3 是Iterator
# python 2 ['1', '2', '3', '4', '5', '6', '7', '8', '9'] ,是可迭代对象,但不是Iterator
14、Django如何在Model保存前做一定的固定操作,比如写一条日志
利用Django的Model的Signal Dispatcher,通过django.db.models.signals.pre_save()方法,在事件发生前,发射触发信号,这一切都被调度中的receiver方法深藏功与名的保存了。
信号的处理一般都写在Model中,举个例子:
import logging
from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver
class Order(models.Model):
# ...
logger = logging.getLogger(__name__)
@receiver(pre_save, sender=Order)
def pre_save_handler(sender, **kwargs):
#我们可以在Order这个Model保存之前尽情调戏了:)
logger.debug("{},{}".format(sender, **kwargs))
参考:http://python.jobbole.com/81871/
15、1,2,3,4,5能组成多少个互不相同的无重复的三位数
5 * 4 * 3
建造者模式 【1】
一、内容
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式与抽象工厂模式相似,也用来创建复杂对象。主要区别是建造者模式着重一步步构造一个复杂对象,而抽象工厂模式着重于多个系列的产品对象。
二、角色
抽象建造者(Builder)
具体建造者(Concrete Builder)
指挥者(Director)
产品(Product)
三、优点
隐藏了一个产品的内部结构和装配过程
将构造代码与表示代码分开
可以对构造过程进行更精细的控制
四、适用场景
当创建复杂对象的算法(Director)应该独立于该对象的组成部分以及它们的装配方式(Builder)时
当构造过程允许被构造的对象有不同的表示时(不同Builder)。
五、实例
# coding : utf-8
# create by ztypl on 2017/5/25
from abc import abstractmethod, ABCMeta
#------产品------
class Player:
def __init__(self, face=None, body=None, arm=None, leg=None):
self.face = face
self.arm = arm
self.leg = leg
self.body = body
def __str__(self):
return "%s, %s, %s, %s" % (self.face, self.arm, self.body, self.leg)
#------建造者------
class PlayerBuilder(metaclass=ABCMeta):
@abstractmethod
def build_face(self):
pass
@abstractmethod
def build_arm(self):
pass
@abstractmethod
def build_leg(self):
pass
@abstractmethod
def build_body(self):
pass
@abstractmethod
def get_player(self):
pass
class BeautifulWomanBuilder(PlayerBuilder):
def __init__(self):
self.player = Player()
def build_face(self):
self.player.face = "漂亮脸蛋"
def build_arm(self):
self.player.arm="细胳膊"
def build_body(self):
self.player.body="细腰"
def build_leg(self):
self.player.leg="长腿"
def get_player(self):
return self.player
class PlayerDirector:
def build_player(self, builder):
builder.build_body()
builder.build_arm()
builder.build_leg()
builder.build_face()
return builder.get_player()
director = PlayerDirector()
builder = BeautifulWomanBuilder()
p = director.build_player(builder)
print(p)
六、UML图
面试题(二)【12】
1、什么是lambda函数?它有什么好处?另外python在函数编程方面提供了些什么函数和语法?
lambda是Python中的匿名函数。它语法简单,简化代码,不会产生命名冲突,污染命名空间。Python提供了map,reduce,filter等函数方法,提供了装饰器,闭包等语法
2、详细说说tuple、list、dict的用法,它们的特点;
tuple 元祖,固定长度不可变的顺序容器,访问效率高,是和存储一些常量数据,可以作为字典的键使用
list 列表,是长度可变有序的数据存储容器,。可以通过下标索引取到相应的数据
dict 字典,长度可变的hash字典容器。存储的方式为键值对,可以通过相应的键获取相应的值,key支持多种类型
3、说说python中装饰器、迭代器的用法;描述下dict的items()方法与iteritems()方法的不同;
装饰器是指对函数执行过程,做一些扩展,甚至可以更改本身函数的执行
迭代器是指遵循迭代器协议的对象,这类对象在被for循环时,每次迭代生成下一个项,不用一开始就生成整个列表
在python3中不存在iteritems,items方法返回可迭代对象
在python2中items()返回[(key,value)]的列表对象,iteritems()返回迭代器对象,iteritems()循环时不可以增删dict的内容
4、讲讲对unicode, gbk, utf-8等的理解,python2.x是如何处理编码问题?
unicode编码:为了解决各个国家的语言的存储,引进的unicode码,包括UCS2,UCS4,UTF-8,UTF-7等
gbk:和unicode不一样的编码方式,常用的为gbk-2312
utf-8: UTF-8 使用 1-4 个字节来存储单个字符,应该是目前最流行的字符集。Linux 默认字符集就是UTF-8。既解决了大多数语言的编码方式,又避免了简单字符存储对空间的浪费
python 2.x需要在文件上方声明文件的编码方式# -*- coding: utf8 -*-,可以通过str.decode/str.encode处理字符串的文本编码
保证 python 编辑器的编码正确,或使用 u’中文’保证被转换成 unicode 编码,推荐使用
sys.setdefaultencoding('utf-8')来保证我们的编码
5、Python 是如何进行内存管理的?python 的程序会内存泄露吗?说说有没有什么方面防止或检测内存泄露?
Python GC主要使用 引用计数 来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”解决容器对象可能产生的循环引用问题。通过分代
以空间换时间的方法提高垃圾回收效率
1、引用计数: 每个对象中都有ob-refcnt来做引用计数。当一个对象...,ob-refcnt就会增加,当引用的对象删除,那么ob-refcnt就会减少当ob-refcnt为零,就会释放该对象的内存空间
2、标记清除: 解决循环引用的问题。先按需分配,等到没有空闲内存的时候,从寄存器和程序栈上的引用出发,遍历所有对象和引用把所有能访问的打标记,最后将没有标记的对象释放掉
3、分代技术: 提高效率,提高垃圾回收的效率,按照存活时间,分成不同的集合。将内存块按照其存活时间划分为不同的集合。每个集合就称为一个“代”,垃圾回收的频率随代的存活时间增大而减小。。Python默认定义分代对象集合,引用数越大,对象的存活时间越长
Python也会内存泄露,Python本身的垃圾回收机制无法回收重写了__del__的循环引用的对象
程序员管理好每个python对象的引用,尽量在不需要使用对象的时候,断开所有引用
尽量少通过循环引用组织数据,可以改用weakref做弱引用或者用id之类的句柄访问对象
通过gc模块的接口可以检查出每次垃圾回收有哪些对象不能自动处理,再逐个逐个处理
6、关于 python 程序的运行性能方面,有什么手段能提升性能?
1、使用多进程,充分利用机器的多核性能
2、对于性能影响较大的部分代码,可以使用C或C++编写
3、对于IO阻塞造成的性能影响,可以使用IO多路复用来解决
4、尽量使用python的内建函数
5、尽量使用局部变量
7、list对象alist [{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}],请按alist中元素的age由大到小排序;
def sort_by_age(list1):
return sorted(alist,key=lambda x:x['age'],reverse=True)
8、两个list对象alist ['a','b','c','d','e','f'], blist ['x','y','z','d','e','f'],请用简洁的方法合并这两个list,并且list里面的元素不能重复;
alist = ['a','b','c','d','e','f']
blist = ['x','y','z','d','e','f']
def merge_list(*args):
s = set()
for i in args:
s = s.union(i)
return list(s)
9、打乱一个排好序的list对象alist;
import random
random.shuffle(alist)
10、简单实现一个stack
class Stack:
def __init__(self):
self.items = []
def __iter__(self):
return self.items.__iter__()
def pop(self):
return self.items.pop()
def top(self):
if len(self.items) > 0:
return self.items[len(self.items) - 1]
def push(self, item):
self.items.append(item)
def empty(self):
self.items = []
def size(self):
return len(self.items)
11、输入某年某月某日,判断这一天是这一年的第几天?(可以用 python 标准库)
import datetime
def dayofyear():
year = input("请输入年份:")
month = input("请输入月份:")
day = input("请输入天:")
date1 = datetime.date(year=int(year),month=int(month),day=int(day))
date2 = datetime.date(year=int(year),month=1,day=1)
return (date1 -date2).days
12、将字符串:"k:1|k1:2|k2:3|k3:4",处理成python字典:{k:1, k1:2, ... }
str1 = "k:1|k1:2|k2:3|k3:4"
def str2dict(str1):
dict1 = {}
for iterms in str1.split('|'):
key,value = iterms.split(':')
dict1[key] = value
return dict1
面试题(三)【1】
请完成一个程序,并能按步骤实现以下功能:
1.下载https://en.wikipedia.org/wiki/Machine_translation页面的内容并保存为mt.html
需要编写代码来下载页面。
2.统计mt.html中
标签内下所有单词以及数目并存储到mt_word.txt中。
mt_word.txt有如下几点要求:
a) 每个单词一行。单词在前,单词出现的次数在后,中间用Tab(\t)进行分隔。
b) 单词要按照单词数目从多到少的顺序进行排列。比如说单词a出现了100次,单词b出现了10次,则单词a要在单词b的前面。
3. 提取出mt.html中所有的年份信息(比如说页面中的1629, 1951这些的四位数字就是年份)存储到mt_year.txt中。
mt_year.txt有如下几点要求:
a)每个年份是一行。
a) 年份需要从过去到现在的顺序进行排列。比如说文章中出现了2007和1997,则1997需要排在2007的前面。
要求:
1. 仅限python编程,而且仅仅可以使用python自带的函数或库。
2.提交可执行的程序以及mt.html, mt_word.txt, mt_year.txt。
3. 限定在一个小时内完成。
# 1.下载https://en.wikipedia.org/wiki/Machine_translation页面的内容并保存为mt.html需要编写代码来下载页面。
session = requests.session()
response = session.get(url="https://en.wikipedia.org/wiki/Machine_translation")
with open('mt.html','wb') as f:
f.write(response.content)
# 2、统计mt.html中
标签内下所有单词以及数目并存储到mt_word.txt中
# 解析页面,拿到所有的p标签中的文本
soup = BeautifulSoup(response.text,features="lxml")
tag2 = soup.find_all(name='p')
list_p = []
for i in tag2:
list_p.append(i.get_text())
# 将所有的文本合并成一个字符串
str_p = ' '.join(list_p)
word_set = set()
for word in str_p.split():
word = word.strip(',.()""/; ')
word_set.add(word)
# word_dict = {}
word_list = []
for word in word_set:
if word == '':
continue
# word_dict[word] = str_p.count(word)
dict2 = {word:str_p.count(word)}
word_list.append(dict2)
# 将单词按照数目反序排列,然后写入文件
blist = sorted(word_list,key = lambda x:list(x.values())[0],reverse =True)
with open('mt_word.txt','w') as f:
for item in blist:
for k,v in item.items():
line = k + '\t' + str(v) + '\n'
f.write(line)
# 3、提取出mt.html中所有的年份信息(比如说页面中的1629, 1951这些的四位数字就是年份)存储到mt_year.txt中
year = re.compile(r'\d{4}')
years_list = re.findall(year,response.text)
years_list = sorted(list(set(years_list)))
with open('mt_year.txt','w') as f:
for year in years_list:
line = year + '\n'
f.write(line)
答案
面试题(四)爬虫【16】
一、试列出至少三种目前流行的大型数据库的名称:________、_________、__________,其中您最熟悉的是__________,从__________年开始使用。
Oracle,Mysql,SQLServer Oracle根据自己情况
二、有表List,并有字段A、B、C,类型都是整数。表中有如下几条记录:
ABC
279
564
3119
现在对该表一次完成以下操作:
查询出B和C列的值,要求按B列升序排列
写出一条新的记录,值为{7,9,8}
查询C列,要求消除重复的值,按降序排列
写出完成完成以上操作的标准的SQL语句,并且写出操作3的结果。
create table List2(A int ,B int,C int)
select B,C from List order by B
insert into List values(7,9,8)
select distinct(C) from List order by 1 desc;
9 8 4
三、请简要说明视图的作用
1. 数据库视图隐藏了数据的复杂性。
2. 数据库视图有利于控制用户对表中某些列的访问。
3. 数据库视图使用户查询变得简单。
四、列举您使用过的python网络爬虫所用到的网络数据包(最熟悉的在前):
requests、urllib、urllib2、httplib2
五、列举您使用过的python网络爬虫所用到的解析数据包(最熟悉的在前):
BeautifulSoup、pyquery、Xpath、lxml
六、列举您使用过的python中的编码方式(最熟悉的在前):
UTF-8,ASCII,gbk
七、python3.5语言中enumerate的意思是_______________________
对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值
enumerate多用于在for循环中得到计数
八、99的八进制表示是_______________________
143
九、请举出三种常用的排序算法
冒泡、选择、快速
十、列出比较熟悉的爬虫框架
Scrapy
十一、用4、9、2、7四个数字,可以使用+、-、*和/,每个数字使用一次,使表达式的结果为24,表达式是_____________________________
(9+7-4)*2
十二、 对你最有影响的或是您认为最有价值的软件方面的几本书是?
十三、您最熟悉的Unix环境是_____________.Unix下查询环境变量的命令是________,查询脚本定时任务的命令是____________________
1 AIX,env crontab
十四、 写出在网络爬虫爬取数据的过程中,遇到的防爬虫问题的解决方案
通过headers反爬虫:解决策略,伪造headers
基于用户行为反爬虫:动态变化去爬取数据,模拟普通用户的行为
基于动态页面的反爬虫:跟踪服务器发送的ajax请求,模拟ajax请求
十五、阅读以下Python程序
for i in range(5,0,-1):
print(i)
请在下面写出打印结果
5 4 3 2 1
十六、在某系统中一个整数占用两个八位字节,使用Python按下面的要求编写完整程序。
接收从标准输入中依次输入的五个数字,将其组合成为一个整数,放入全局变量n中,随后在标准输出输出这个整数。(ord(char)获取字符ASCII值的函数)
面试题(五)爬虫 【14】
1、post、get有什么区别?
1. 根据HTTP规范,GET一般用于获取/查询资源信息,应该是安全的和幂等。而POST一般用于更新资源信息
2. get是在url中传递数据,数据放在请求头中。 post是在请求体中传递数据
3. get传送的数据量较小,只能在请求头上发送数据。post传送的数据量较大,一般被默认为不受限制。
5. get安全性非常低,post安全性较高。但是执行效率却比Post方法好。
建议:
1、get方式的安全性较Post方式要差些,包含机密信息的话,建议用Post数据提交方式;
2、在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式;
2、http、https协议有什么区别?
http协议是超文本传输协议,被用于在web浏览器和网站服务器之间传递信息。http协议工作是以明文方式发送内容,不提供任何形式的数据加密,而这也是很容易被黑客利用的地方,如果黑客截取了web浏览器和网站服务器之间的传输信息,就可以直接读懂其中的信息,因此http协议不适合传输一些重要的、敏感的信息,比如信用卡密码及支付验证码等。
安全套接字层https协议就是为了解决http协议的这一安全缺陷而出生的,为了数据传输的安全,https在http的基础上加入了ssl协议,ssl依靠证书来验证服务器的身份,为浏览器和服务器之间的通信加密,这样的话即使黑客借去了发送过程中的信息,也无法破解读懂它,我们网站及用户的信息便得到了最大的安全保障。
https协议需要到ca申请证书,一般免费证书很少,需要费用。
http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议
http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。
http的连接很简单,是无状态的, HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全
3、 域名和IP之间有什么关系,如何查看某个域名对应的所有IP?
国际互联网(Internet)上有成千百万台主机(host),为了区分这些主机,人们给每台主机都分配了一个专门的“地址”作为标识,称为IP地址
由于IP地址全是些的数字,为了便于用户记忆,Internet上引进了域名服务系统DNS(Domain Name System)。
当您键入某个域名的时候,这个信息首先到达提供此域名解析的服务器上,再将此域名解析为相应网站的IP地址。完成这一任务的过程就称为域名解析。
1.ping 2.nslookup 3.使用站长工具等
4、http协议头中,keep-alive字段有什么作用?
HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器都要新建一个连接,完成 之后立即断开连接(HTTP协议为无连接的协议);
当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服 务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。
通过使用keep-alive机制,可以减少tcp连接建立次数,也意味着可以减少TIME_WAIT状态连接,以此提高性能和提高httpd服务器的吞吐率(更少的tcp连接意味着更少的系统内核调用,socket的accept()和close()调用)。
5、robots协议是什么?
Robots协议(也称为爬虫协议、爬虫规则、机器人协议等)也就是robots.txt,网站通过robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。
Robots协议是网站国际互联网界通行的道德规范,其目的是保护网站数据和敏感信息、确保用户个人信息和隐私不被侵犯。因其不是命令,故需要搜索引擎自觉遵守。
6、 列出几种常见的关系型数据库和非关系型数据库?(每种至少两个)
Oracle、Mysql、SQLServer、DB2 Redis MongoDB Cassandra
7、 内存泄露是什么?如何避免?
指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。
内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
导致程序运行速度减慢甚至系统崩溃等严重后果。
有 __del__() 函数的对象间的循环引用是导致内存泄漏的主凶。
不使用一个对象时使用:del object 来删除一个对象的引用计数就可以有效防止内存泄漏问题.
通过 Python 扩展模块 gc 来查看不能回收的对象的详细信息
可以通过 sys.getrefcount(obj) 来获取对象的引用计数,并根据返回值是否为 0 来判断是否内存泄漏
Python的内存管理机制
1.引用计数:通过引用计数来保持对内存中的变量跟踪,Python内部记录中所有在使用对象各有多少个引用。
Python中有个内部跟踪变量叫做引用计数器,每个变量有多少个引用,简称引用计数。当对象被创建时就创建了一个引用计数。
当某个对象的引用计数为0时,对象就不在需要,就列入了垃圾回收队列。
引用计数增加:1.对象被创建:x=4;2.另外的别人被创建:y=x;3.被作为参数传递给函数:foo(x);4.作为容器对象的一个元素:a=[1,x,'33'];
引用计数减少时:1.一个本地引用离开了它的作用域。比如上面的foo(x)函数结束时,x指向的对象引用减1;
2.对象的别名被显式的销毁:del x;或者del y;
3.对象的一个别名被赋值给其他对象:x=789
4.对象从一个窗口对象中移除:myList.remove(x)
5.窗口对象本身被销毁:del myList,或者窗口对象本身离开了作用域。
2.垃圾回收
1.引用计数: 每个对象中都有ob-refcnt来做引用计数。当一个对象...,ob-refcnt就会增加,当引用的对象删除,那么ob-refcnt就会减少当ob-refcnt为零,就会释放该对象的内存空间
2.标记清除: 解决循环引用的问题。先按需分配,等到没有空闲内存的时候,从寄存器和程序栈上的引用出发,遍历所有对象和引用把所有能访问的打标记,最后将没有标记的对象释放掉
3.分代技术: 提高效率,提高垃圾回收的效率,按照存活时间,分成不同的集合。将内存块按照其存活时间划分为不同的集合。每个集合就称为一个“代”,垃圾回收的频率随代的存活时间增大而减小。。Python默认定义分代对象集合,引用数越大,对象的存活时间越长
3.内存池机制
在Python中,大多数申请的都是小块的内存,会执行大量的malloc和free操作。Python引入了一个内存池机制,用于管理对小块内存的申请和释放,即Pymalloc机制。
它将不用的内存放到内存池而不是返回给操作系统。
1. 当申请的内存小于256字节时,PyObject_Malloc会在内存池中申请内存;当申请的内存大于256字节时,PyObject_Malloc的行为将蜕化为malloc的行为。当然,通过修改Python源代码,我们可以改变这个默认值,从而改变Python的默认内存管理行为。
2. 对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。
8、 列举几个常用的dom解析项目、插件
xml、libxml2、lxml、xpath
9、 常见的反爬虫机制有哪些?
通过headers反爬虫:解决策略,伪造headers
基于用户行为反爬虫:动态变化去爬取数据,模拟普通用户的行为
基于动态页面的反爬虫:跟踪服务器发送的ajax请求,模拟ajax请求
10、如何提高爬取效率?
1. 爬取方面,利用异步io。
2.处理方面,利用消息队列做生产者消费者模型
11、楼梯问题
1.1、给一个楼梯,从最下面往上走,每次可以走1到n步,求总共有多少种走法?
1.2、给一个楼梯,从最下面往上走,每次可以走1步或2步,求总共有多少种走法?
1.3、给一个楼梯,从最下面往上走,每次可以走1步或2步或3步,求总共有多少种走法?
# 1、 给一个楼梯,从最下面往上走,每次可以走1或2步,求总共有多少种走法?
# 假设只有一个台阶,那么只有一种跳法,那就是一次跳一级,f(1)=1;如果有两个台阶,那么有两种跳法,第一种跳法是一次跳一级,第二种跳法是一次跳两级,f(2)=2。
# 如果有大于2级的n级台阶,那么假如第一次跳一级台阶,剩下还有n-1级台阶,有f(n-1)种跳法,假如第一次条2级台阶,剩下n-2级台阶,有f(n-2)种跳法。这就表示f(n)=f(n-1)+f(n-2)。
def walk_stairs(stairs):
if stairs == 1:
return 1
if stairs == 2:
return 2
else:
return walk_stairs(stairs-1) + walk_stairs(stairs-2)
# 2、给一个楼梯,从最下面往上走,每次可以走1到n步,求总共有多少种走法?
#上1个台阶1
#上2个台阶2
#上3个台阶4
#上4个台阶8
#上n个台阶2^(n-1)
# 3、给一个楼梯,从最下面往上走,每次可以走1步或2步或3步,求总共有多少种走法?
#上1个台阶2^(1-1)
#上2个台阶2^(2-1)
#上3个台阶2^(3-1)
# f(n) = f(n-1) + f(n-2) + f(n-3)
12、 给一个字符数组,字符包含a-z、1-9,比如:a b c 4 b 2 a c 1 1 3,求只出现一次的第一次出现的字符
str_list = ['a', 'b', 'c', 4, 'b', 2, 'a', 'c', 1, 1, 3]
def find_only_one(alist):
for string in alist:
count = alist.count(string)
if count == 1:
return string
return None
13、 有一个html文本字符串,让我取出sflkj这个a标签里面的href的链接地址?
from bs4 import BeautifulSoup
text = "sflkj"
the_html = BeautifulSoup(text,features='lxml')
print(the_html.find('a').attrs['href'])
14、 下面是一个单线程的代码,请改写成多线程的:
start = "http://google.com"
queue = [start]
visited = {start}
while queue:
url = queue.pop(0)
print(url)
for next_url in extract_url(url):
if next_url not in visited:
queue.append(next_url)
visited.add(next_url)
from concurrent.futures import ThreadPoolExecutor
start = "http://google.com"
queue = [start]
visited = {start}
pool = ThreadPoolExecutor(10)
def func(url):
for next_url in extract_url(url):
if next_url not in visited:
queue.append(next_url)
visited.add(next_url)
while queue:
url = queue.pop(0)
pool.submit(func,url)
pool.shutdown(wait=True)
面试题(六)[17]
1、 获取list的元素个数,向list的末尾追加元素所用的方法分别是( ),( )
count,append
2、 判断dict有没有某个key用的方法是( )
in
3、 L = range(100) ,取第一到第三个元素用(),取倒数第二个元素(),取后十个元素()
L[:3]
L[-2]
L[-10:]
4、 把L复制给L1用() 注意:非引用传递
L1 = L.copy()
5、d = {'a':1,'b':2,'c':3}请打印出key,value对
for k,v in d.items():
print(k,v)
6、 如何判断一个变量是不是字符串
isinstance(a,str)
7、list和tuple有什么不同?
8、xrange和range有什么不同?
9、‘1,2,3’如何变成[‘1’,’2’,’3’] ? [‘1’,’2’,’3’]如何变成[1,2,3]
s1 = "1,2,3"
s2 = list(s1.split(','))
s3 = list(map(int,s2))
10、请回答以下问题?
def add_end(L= []):
L.append('END')
return L
print(add_end()) #输出什么?
print(add_end()) #再次调用输出什么?为什么?
["END"] ["END",""END] 函数的默认参数在编译时,分配内存空间。没有给予参数都是使用默认的参数,是同一段内存地址的同一对象。
11、[36,5,12,9,21]怎么排序?
a = [36,5,12,9,21]
a.sort()
12、请回答以下问题:
def func(a,b,c=0,*args,**kwargs):
pass
*args,**kwargs的作用是什么?
当函数的参数不确定时,可以使用*args 和**kwargs来 传递可变参数。
*args储存可变的位置参数,它会接收任意多个参数并把这些参数作为元组传递给函数。**kwargs存储可变的关键字参数,允许你使用没有事先定义的参数名,将接收到任意多个关键字参数作为字典传递给函数。
注意函数的参数的顺序:args必须在kwargs前面,调用函数传递参数也必须依照此顺序
13、is和==的区别是?
Python中的对象包含三要素:id、type、value
其中id用来唯一标识一个对象,type标识对象的类型,value是对象的值
is判断的是a对象是否就是b对象,是通过id来判断的
==判断的是a对象的值是否和b对象的值相等,是通过value来判断的
14、如何生成[1,4,9,16,25,36,49,64,81,100]?尽量用一行实现
[x*x for x in range(1,11)]
15、生成器是什么?有什么作用?请写出一个生成器
a = ( i for i in range(11))
16、map(str,[1,2,3,4,5,6,7,8,9])输出什么?
# 生成的是map对象
print(list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
# ['1', '2', '3', '4', '5', '6', '7', '8', '9']
17、请写出log的实现(主要功能是打印函数名)
@log
def now():
print('2013-12-25')
now()
# 输出:
# call now()
# 2013-12-25
import functools
def log(func):
@functools.wraps(func)
def inner():
print('call '+ func.__name__ + '()')
func()
return inner
面试题(七)[13]
一、单项选择
1 以下叙述正确的是:
A continue语句的作用是结束整个循环的执行
B 只能在循环体内和switch语句体中使用break语句
C 在循环体内使用break语句或continue语句的 作用相同
D 从多层循环嵌套中退出时,只能使用goto语句
# B
2 Python如何定义一个函数( 3)
class ( arg1 , arg 2, ... , argN)
function (arg1 ,arg2 ,… , argN)
def (arg1 ,arg2 ,… , argN)
def ( arg1 , arg 2, ... , argN)
3 下面哪个函数能够在Linux环境下创建一个子进程:
os.popen
os.fork
os.system
os.link
# 2
4已知x=43,ch = 'A' ,y = 1,则表达式(x > y and ch< ‘B’ and y)的值是
0
1
出错
True(“真”)
# 2
5 下面的语句哪个会无限循环下去
启动range函数原型为range([start],stop[,step])
1、for a in range(10):
time.sleep(10)
2、while 1 < 10:
time.sleep(10)
3、while True:
break;
4、a = [3,-1, 5 , 7]
for I in a[:]
if a > 10:
break;
# 2
6 下列表达式中返回为True的是:
A. 3 > 2 >2
B. ‘abc’ > ‘xyz’
C. 0x56 < 56
D. (3,2) < (‘a’,’b’)
# D
7 Python不支持的数据类型有
char
int
float
list
# 1
二、不定选项
8 下面的函数,那些会输出1,2,3三个数字
for I in range(3)
print i
2. aList = [0,1,2]
for I in aList:
print i+1
3. I = 1
while I < 3:
print i
I = I +1
4.for I in range(3):
print I + 1
# 2,4
三、填空题
9 以下函数需要调用在其中引用一个全局变量k,请填写语句:
def func():
___________
k = k +1
global k
10请把以下函数转化为Python lambda匿名函数
def add(x,y):
return x+y
lambda x,y:x+y
11请简单解释Python中static method(静态方法)和class method(类方法)
请将以下代码填写完整
class A(object):
def foo(self,x):
print("executing foo(%s,%s)" % (self,x))
@classmethod
def class_foo(cls,x):
print("executing class_foo(%s,%s)" % (cls,x))
@staticmethod
def static_foo(x):
print("executing static_foo(%s)" % (x))
a = A()
# 调用 foo函数,参数传入1
a.foo(1)
#调用class_foo函数,参数传入1
a.class_foo(1)
A.class_foo(1)
# 调用静态方法,传入参数1
a.static_foo(1)
A.static_foo(1)
四、程序题
12、 请书写一个函数,用于替换某个字符串的一个或某几个字串
函数原型strreplace(str,oldString,newString);
例如:
pstr = “Hello World!”
afterReplaceStr = strreplace(pstr,”World”,”Tom”)
那么afterReplaceStr的值为”Hello Tom”
def strreplace(str,oldString,newString):
return str.replace(oldString,newString)
13、 平衡点问题:
假如一个数组中的元素,其前面的部分等于后面的部分,那么这个点的位序就是平衡点
比如一个列表numbers = [1,3,20,2,18,6],2前面的总和为24,2后面的总和也是24,那么2就是平衡点
要求编写程序,寻找并返回任意一个列表的平衡点
def balance_num(numbers):
for i in range(0,len(numbers)):
if sum(numbers[:i]) == sum(numbers[i+1:]):
return numbers[i]
return None
面试题(八)【11】
1 Python如何实现单例模式?
2什么是lambda函数?
3 请写出一段Python代码实现删除list里面的重复元素?
4 如何用Python删除一个文件?
5 Python里面如何生成随机数?
6 请用Python写出一个获取用户输入数字,并根据数字大小输出不同信息的脚本?
7 range和xrange区别
8 解释生成器(generator)与函数的不同,并实现和使用简单generator
9输入一个字符串,返回倒序排列的结果;如’abcdef’,返回’fedcba’ str1 = 'abcdefg'
str2 = str1[::-1]
str3 = list(str1)
str3.reverse()
str4 = ''.join(str3)
10 请使用自己的算法,按升序合并如下两个list,并去除重复的元素:
list1 = [2,3,8,4,9,5,6]
list2 = [5,6,10,17,11,2]
11.Django如何在Model保存前做一定的固定操作,比如写一句日志
面试九【4】
1、浅谈你对python编码规范的认识,并写出你知道的编码规范
一、原因
1、长期的工作中,发现大多数程序员的代码可读性差
2、不同的程序员之间的协作很重要,代码可读性必须很好
3、版本升级时,要基于源码升级
4、不友好的代码会影响python的执行效率
二、基于的规范
1、PEP 8: Style Guide for Python Code---------Python的编码风格建议
2、Google Python Style Guide--------------Goole Python编码风格建议
三、Python语言规范
1. imports 仅仅用做包和模块的导入,包的导入每个尽量独占一行
2. packages 导入模块尽量使用模块的全路径
3. Exceptions必须小心使用
4. Global variables避免使用全局变量
5. Generator
6. lambda 函数仅仅适用于一行代码能实现的简单函数
7. True or False尽量使用[],'',{},0,None来隐式表示False
四、Python风格规范
1、代码编排
1 缩进:4个空格实现缩进,尽量不使用Tab,禁止混用Tab和空格
2 行:每行最大长度不超过79,换行可以使用反斜杠(\)。最好使用圆括号将换行内容括起来,不建议使用“;”
3 空行:类和top-level函数定义之间空两行;类中的方法定义之间空一行;函数内逻辑无关段落之间空一行;其他地方尽量不要再空行。
4 空格:括号内的第一个位置,不要空格。紧靠右括号的位置也不要空格。冒号(:)、逗号(,)、分号(;)之前不要加空格。切片木有参数,不要加空格等
5 括号:对于单元素tuple一定要加,和括号
2、命名规范
module_name
package_name
ClassName
method_name
ExceptionName
function_name
GLOBAL_CONSTANT_NAME
global_var_name
instance_var_name
function_parameter_name
local_var_name
3、注释规范
1.块注释,在一段代码前增加的注释。在‘#’后加一空格。段落之间以只有‘#’的行间隔。比如:
# Description : Module config. # # Input : None # # Output : None
2. 行注释,在一句代码后加注释。比如:x = x + 1 # Increment x 但是这种方式尽量少使用。
3. 避免无谓的注释。
4、编程建议
1. 字符串拼接,尽量使用join。使用str的方法而不是内置方法。使用startswith或endswith拉检查前缀和后缀
2. 单例对象,尽量使用is 、is not,不要使用==
3.使用is not而不是not is
4. 使用def来定义函数,而不是将匿名函数赋给某个变量
5. 尽量使代码整齐,简洁
6.使用isinstance()来判断instance的类型
2、浅谈你对python安全编码的认识,并举例说明
1、图书管理系统是对图书进行录入、借阅的系统,请用django框架实现新增、查看图书的功能,分别写出model.py、urls.py、views.py的逻辑
2、设有一个背包能承受重量s(s>0),又有n(n>=1)件物品,其质量列表为 w = [w1,w2....,wn],要从物品中挑选若干件放入背包,使得放入的图书质量之和正好是s。请设计递归函数f(w,s,n):
当有解时,返回True,并显示所选物品是那些?无解时返回False。提示:[递归之处在于f(w,s-wn,n-1) or f(w,s,n-1)]
python面试题(十)【10】
Python中基本数据结构的操作
元组列表字典集合
定义
新增
更改
删除
2.请尽可能列举python列表的成员方法,并给出一下列表操作的答案:
(1)a=[1, 2, 3, 4, 5], a[::2]=?, a[-2:] =?
(1)1 3 5
(2)4 5
(2) 一行代码实现对列表a中的偶数位置的元素进行加3后求和?
sums = sum(map(lambda x: x + 3, a[1::2]))
3.List = [-2, 1, 3, -6],如何实现以绝对值大小从小到大将List中内容排序。
sorted(list1,key = abs)
(1) 列表的sort方法和 sorted的区别是什么?
sort是list的方法,改变list对象的顺序,返回值为None
sorted是Python的内置方法,适用iterable对象,返回值是新列表,不影响原来的iterable的顺序
4.有一篇英文文章保存在 a.txt 中,请用python实现统计这篇文章内每个单词的出现频率,并返回出现频率最高的前10个单词及其出现次数(只考虑空格,标点符号可忽略)
from collections import Counter
c = Counter()
with open('a.txt','r',encoding='utf-8') as f:
for line in f.readlines():
words = line.split()
c1 = Counter(words)
c.update(c1)
(1)追加需求:引号内元素需要算作一个单词,如何实现?
以"分割,转换成列表,取其奇数分割,其偶数不做处理
5.Python函数中经常有 *args,**kwargs 这两个参数,它们是什么意思,为什么要使用它们?
太简单,就不写啦,哈哈哈哈
6.Python中的变量作用域(变量查找顺序)。
LEGB
local局部变量--->enclosed闭包作用域----> Global全局---->built-in变量
7.下面这段代码的输出结果将是什么?请解释。
# 1 1 1 继承自父类的类属性x,所以都一样,指向同一块内存地址
# 1 2 1更改Child1,Child1的x指向了新的内存地址
# 3 2 3更改Parent,Parent的x指向了新的内存地址
8.描述Python GIL的概念, 以及它对python多线程的影响?编写一个多线程抓取网页的程序,并阐明多线程抓取程序是否可比单线程性能有提升,并解释原因。
Guido的声明:http://www.artima.com/forums/flat.jsp?forum=106&thread=214235
he language doesn't require the GIL -- it's only the CPython virtual machine that has historically been unable to shed it.
Python语言和GIL没有半毛钱关系。仅仅是由于历史原因在Cpython虚拟机(解释器),难以移除GIL。
GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行字节码。
线程释放GIL锁的情况:
在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL
Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100
Python使用多进程是可以利用多核的CPU资源的。
多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁
9.Python中如何动态获取和设置对象的属性。
if hasattr(Parent,'x'):
print(getattr(Parent,'x'))
setattr(Parent,'x',3)
print(getattr(Parent,'x'))
10.(前端基础)
(1)用CSS如何隐藏一个元素
dispaly:none
(2)一行CSS实现padding上下左右分别为1px,2px,3px,4px
padding:1 4 2 3
(3) JavaScript(或jQuery)如何选择一个id为main的容器
$('#main')
(4) JavaScript(或jQuery)如何选择一个class为menu的容器
$('.menu')
python面试(十四)【4】
map(lambda x:x*x,[y for y in range(3)])
[0, 1, 4]
2、下面代码会输出什么?
def f(x, l = [] )
for i in range(x):
l.append(i*i)
print l
f(2)
f(3,[3,2,1])
f(3)
1、[0, 1]
2、[3, 2, 1, 0, 1, 4]
3、[0, 1, 0, 1, 4]
之一,示例如下:
层级遍历:0 1 2 3 4 5 6 7 8 9
先序遍历:0 1 3 7 8 4 9 2 5 6
中序遍历:7 3 8 1 9 4 0 5 2 6
后序排列:7 8 3 9 4 1 5 6 2 0
class Node(object):
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
r为Node类型的根节点
实现函数traverse(r)输出先序遍历结果,输出部分使用print r.data即可
node7 = Node(7)
node8 = Node(8)
node9 = Node(9)
node3 = Node(3,node7,node8)
node4 = Node(4,node9)
node5 = Node(5)
node6 = Node(6)
node1 = Node(1,node3,node4)
node2 = Node(2,node5,node6)
node0 = Node(0,node1,node2)
def traverse(r):
print(r.data)
if r.left:
traverse(r.left)
if r.right:
traverse(r.right)
4、有一个3G大小的文件,文件每行一个string,内容为酒店的id和一个图片的名字,使用“\t”分割
示例:ht_1023134 + "\t" + hidfadsfadsfdfadsf2r234523,jpg
表示的是一个酒店包含的一张图片,统计含有图片数量为[20,无穷大]的酒店id,含有图片数量为[10,20]的酒店id、含有图片数量为[10,5]的酒店id,含有图片数量为[0,5]的酒店id,并将结果输出到文件中
0-5 + “\t” + id1 + “\t” + id2 + .....
5-10 + “\t” + id1 + “\t” + id2 + .....
10-20 + “\t” + id1 + “\t” + id2 + .....
20-无穷大+ “\t” + id1 + “\t” + id2 + .....
from collections import Counter
count_dict = {}
cou = Counter()
with open('a.txt', encoding='utf-8') as f:
for line in f:
hotel, image = line.split()
hotel_id = hotel.split('_')[1]
cou.update({hotel_id,1})
if hotel_id in count_dict:
count_dict[hotel_id] += 1
else:
count_dict[hotel_id] = 1
del cou[1]
zero_five = ['0-5']
five_ten = ['5-10']
ten_twenty = ['10-20']
twenty_infinite = ['10-去穷大']
for hotel_id,count in count_dict.items():
if count < 5 :
zero_five.append(hotel_id)
elif count < 10 :
five_ten.append(hotel_id)
elif count < 20:
ten_twenty.append(hotel_id)
else:
twenty_infinite.append(hotel_id)
with open('b.txt','w',encoding='utf-8') as b:
b.write('\t'.join(zero_five))
b.write('\n')
b.write('\t'.join(five_ten))
b.write('\n')
b.write('\t'.join(ten_twenty))
b.write('\n')
b.write('\t'.join(twenty_infinite))
面试题(十五)【13】
1、请简要描述django-admin.py makemessages的作用
2、Python如何捕获异常,如何在程序执行过程中抛出异常机制?
Python中使用try ... except SomeException as e: ...来捕获异常
raise SomeException("Some Message")来抛出异常
3、什么是lambda函数?它有什么好处?
4、*args和**kwargs的使用方法,请简述一下?
5、简要介绍下python里面的装饰器?
6、Http请求中GET和POST有什么区别?Cookies和Session有什么区别?
7、a = 1,b = 2,不用中间变量交换a和b的值?
b, a = a, b
Python支持不使用中间变量交换两个变量的值
8、编写一个函数删除list里的重复元素,用两种方式实现?
9、请简要概括django测试工具?
10、如何扩展auth_user的字段
11、请给出Profile的实现实例
12、如何替换auth_user
13、django的继承的方式有哪些?
Python面试题(十六)【8】164
1、取出两个升序数组中的最小的一半的元素组成一个新的升序数组。
map(lambda x, y: x if x < y else y, a, b)
2、用至少2种不同的方式删除一个list里面的重复元素
a = [1, 2, 2, 4, 34, 3, 4, 56, 65, 456, 5, 6456, 456, 54, 45, 6, 464, 564]
# 方法一
new_list3 = list(set(a))
# 方法二
new_list = []
for num in a:
if num not in new_list:
new_list.append(num)
# 方法三
dict1 = dict.fromkeys(a)
new_list2 = dict1.keys()
3、利用线程池(10个线程)实现一个并行打印10行信息的程序,打印This is thread xx.(注:xx为线程id)
4、关系型数据库的事务隔离级别有哪些,分别有什么影响?
1、未提交读(Read Uncommitted)
直译就是"读未提交",意思就是即使一个更新语句没有提交,但是别的事务可以读到这个改变.这是很不安全的。允许任务读取数据库中未提交的数据更改,也称为脏读。
2、提交读(Read Committed)
直译就是"读提交",可防止脏读,意思就是语句提交以后即执行了COMMIT以后别的事务就能读到这个改变. 只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别
3、可重复读(Repeatable Read):
直译就是"可以重复读",这是说在同一个事务里面先后执行同一个查询语句的时候,得到的结果是一样的.在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
4、串行读(Serializable)
直译就是"序列化",意思是说这个事务执行的时候不允许别的事务并发执行. 完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
四,隔离级别对事务并发的控制
下表是各隔离级别对各种异常的控制能力:
丢失更新 脏读 非重复读 二类丢失更新(覆盖更新) 幻像读
未提交读 Y Y Y Y Y
提交读 N N Y Y Y
可重复读 N N N N Y
串行读 N N N N N
5、请用python编写函数find_string,从文本中搜索并打印内容,要求支持通配符星号和问号。
例子:
>>>find_string('hello\nworld\n','wor')
['wor']
>>>find_string('hello\nworld\n','l*d')
['ld']
>>>find_string('hello\nworld\n','o?')
['or']
6、请为find_string编写单元测试
7、已有一个字典列表,如下:
li = [
{'id': '1.1', 'content': "14"},
{'id': '1.2', 'content': "15"},
{'id': '1.3', 'content': "16"},
{'id': '1.4', 'content': "17"},
{'id': '1.5', 'content': "18"},
]
请写一个类:
abc = x()
>>abc['1.1']
14
class x(UserDict):
def __init__(self):
super().__init__()
for dic in li:
# print(dic)
self.data.update({dic['id']:dic['content']})
abc = x()
print(abc['1.1'])
8、如何快速对学生的成绩进行评级:(源自Fluent Python)
60分以下评为F
60-70评为D
...
90分以上为A
import bisect
import sys
def grade(score, breakpoint=[60, 70, 80, 90], grades = 'FDCBA'):
i = bisect.bisect(breakpoint, score)
return grades[i]
if __name__ == '__main__':
level = grade(64)
print(level)
面试问题总结【25】
1、WebSocket相关问题
请简单说明一下WebSocket的握手过程
1、client发送请求,请求头携带Sec-WebSocket-Key
2、server收到请求,解析请求头部信息,拿到Sec-WebSocket-Key
3、服务器端将magic_string(258EAFA5-E914-47DA-95CA-C5AB0DC85B11)和Sec-WebSocket-Key进行sha-1加密,将hash结果进行base64编码
4、将编码结果放在响应头部Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=,返回给客户端,连接完成
Tornado如何处理WebSocket
1、Tornado的Controller匹配到响应的请求url,将其转发给处理的Handler,比如ChatHandler
2、ChatHandler需要继承tornado.websocket.WebSocketHandler
3、ChatHandler必须实现
open方法:客户端连接成功,需要执行的方法
on_message方法:客户端向服务端发送消息,执行的方法
on_close方法:客户端关闭时,执行的方法
2、能简单说说线程、进程和协程吗?
1、线程:最小的调度单位
2、协程:用户自定义的线程切换
3、进程:
3、Http和Https的区别?
4、对于TCP/IP协议熟悉吗?三次握手,四次挥手?能简单说一下七层模型吗?
TCP/IP协议,是网络通信协议,又称传输控制协议/因特网互联协议。定义了电子设备如何连入互联网,以及数据如何在互联网相互传输的标准。
所谓三次握手就是建立TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。
(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
所谓四次挥手,就是指断开一个TCP连接时,客户端和服务器总共发送4个包来确认连接的断开。
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
七层模型,即OSI(Open System Interconnect),开放式系统互联
5、能简单说一下你了解的socket吗?
6、Python的GIL(全局解释器锁)
7、Python的with语句?优点?如何实现?
8、Python的单例模式?
9、Python垃圾回收机制?
10、Python的生成器和迭代器?
11、python的装饰器?
12、Python的with语句的使用?
13、Python函数中经常有 *args,**kwargs 这两个参数,它们是什么意思,为什么要使用它们?
14、Django的请求生命周期
用户请求到来 ,通过url进行(自上而下)的路由匹配, 匹配成功则映射到对应视图。
通过业务逻辑的处理(数据库...), 经模板渲染继而响应给用户内容
15、Django的中间件做什么?
中间件是用来处理请求和响应的插件机制,全局地处理Django的请求和响应。每个中间件都有特定功能。MiddleWare的需要在settings里面进行配置,按顺序配置上对应类的在Python中全路径。MiddleWare一般都是MiddlewareMixin的子类。通常实现process_request方法和process_response方法。
process_request是在请求来临时,尚未正则匹配前执行的函数。如果这个函数没有返回值,或者返回为None,会继续执行其他中间件的process_request方法。如果返回HttpResponse,Django将不会执行后序的中间件和views函数,直接将response返回。
process_view函数是在获取到要执行的view函数和相应参数,在view函数执行之前执行的函数。也是可以返回None或HttpResponse。
process_response是在执行完view函数,并生成response之后,执行的函数。可以对response做进一步的处理。必须返回HttpResponse对象。
16、Django的ORM怎么获取到一个name字段总数据有没有“abc”,ORM操作
17、form验证?
18、说一下线程锁,什么时候用?
19、描述你怎么用的tornado?
20、Tornado怎么做到异步的?
21、Scrapy了解多少?
22、爬虫的数据入库操作,线程需要加锁吗?
23、Mysql的优化?
24、了解装饰器吗?可以用来做什么?有什么优缺点?
25、使用过epoll?能聊聊IO多路复用吗?