目录
- 1. 列出5个python标准库
- 2. 字典的删除键和合并
- 3. python实现列表去重的方法
- 4. func(a, b, *arg, **kwarg)
- 5. python2和python3的range(100)的区别
- 6. 一句话解释什么样的语言能够用装饰器?
- 7. python内建数据类型有哪些
- 8. 简述面向对象中__new__和__init__区别
- 9. with open和open
- 10. map()函数
- 10.1 reduce()函数
- 11. 避免转义给字符串加哪个字母表示原始字符串?
- 12. re正则提取
- 13. python中断言方法
- 14. 数据表student有id,name,score,city字段,其中name中的名字可有重复,需要消除重复行,请写sql语句
- 15. python2和python3区别?列举5个
- 16. 列出python中可变数据类型和不可变数据类型,并简述原理
- 17. 字符串去重并排序输出
- 18. lambda函数应用
- 19. 字典根据键从小到大排序
- 20. 利用collections库的Counter方法统计字符串每个单词出现的次数
- 20.1 统计字符串中某个字符出现的次数
- 21. filter方法求出列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- 22. 数据库优化查询方法
- 23. 请列出你会的任意一种统计图(条形图、折线图等)绘制的开源库,第三方也行
- 24. 正则表达式匹配中,(.*)和(.*?)匹配区别?
- 25. [[1,2],[3,4],[5,6]]一行代码展开该列表,得出[1,2,3,4,5,6]
- 26. 异常模块中try except else finally的相关意义
- 27. 说明zip()函数用法
- 28. 写5条常用sql语句
- 29. 提高python运行效率的方法
- 30. 简述mysql和redis区别
- 31. 对列表进行排序,不能用sort
- 32. 写一个单例模式
- 33. 列出常见的状态码和意义
- 34. 使用pop和del删除字典中键值
- 35. 简述cookie和session的区别
- 36. 简述多线程、多进程
- 37. IOError、AttributeError、ImportError、IndentationError、IndexError、KeyError、SyntaxError、NameError分别代表什么异常
- 38. python中copy和deepcopy区别
- 39. 列出几种魔法方法并简要介绍用途
- 40. 迭代器
- 41. 列表推导式、字典推导式、生成器
- 42. 递归求和
- 43. 简述python引用计数机制
- 44. 简述乐观锁和悲观锁
- 45. r、w读写模式
- 46. 两个list的交集并集
- 47. 常见的网络传输协议
- 48. HTTP请求中get和post区别
- 49. python中读取Excel文件的方法
- 50. 简述多线程、多进程
- 51. post的编码方式
- 52. 长链接和短连接
- 53. http协议
- 54. int占几个字节
- 55. 应用层基于TCP和UDP的协议
- 56. 五种进程调度算法
- 57. 常见的数据结构
1. 列出5个python标准库
参考:https://www.cnblogs.com/qingchengzi/articles/10874620.html
os、sys、random、time & datetime、re、hashlib
1.1 os:用于访问操作系统的模块,主要功能:系统相关、目录及文件操作、执行命令、进程管理等。
方法和变量 | 用途 |
---|---|
os.getcwd() | 获取当前工作目录(python脚本所在目录) |
os.chdir(dirname) | 改变到别的目录 |
os.mkdir(dirname) | 创建目录 |
os.rmdir(dirname) | 删除单级空目录,若目录不为空则无法删除并报错 |
os.remove(filename) | 删除文件 |
os.rename(“old”, “new”) | 重命名文件/目录 |
os.path.abspath(path) | 返回绝对路径 |
os.path.dirname(path) | 返回path的上级目录 |
os.path.exists(path/file) | 返回文件或路径是否存在(True/False) |
os.path.getsize(filename) | 返回文件字符数量,可根据是否为0判断文件是否为空 |
os.path.join(path1, path2) | 连接两个或更多的路径名。 如果各组件名首字母不包含’/’,则函数会自动加上 |
os.system(cmd) | 执行命令 |
删除目录或文件的更高级操作:
import shutil
shutil.rmtree(path) # 无论是否为空,都可以删除
python中的os.path.dirname(file)的使用:
(1).当"print os.path.dirname(file)"所在脚本是以完整路径被运行的, 那么将输出该脚本所在的完整路径,比如:
python d:/pythonSrc/test/test.py
那么将输出 d:/pythonSrc/test
(2).当"print os.path.dirname(file)"所在脚本是以相对路径被运行的, 那么将输出空目录,比如:
python test.py
那么将输出空字符串
1.2 sys:针对python的解释器的变量和方法
方法/变量 | 用途 |
---|---|
sys.argv | 获取命令行参数列表 |
sys.exit() | 退出python程序,exit(0)为正常,非0时抛异常 |
sys.path | 返回python的环境变量值 |
sys.getdefaultencoding() | 获取系统编码 |
sys.setdefaultencoding(“utf-8”) | 解决编码报错问题,语句前加reload(sys) |
1.3 random:用于生成伪随机数
方法 | 用途 |
---|---|
random.randint(1, 5) | 随机生成整数 |
random.choice(list) | 从列表中随机选取一个元素 |
random.choice(list, k=3) | 从列表中随机选取3个元素,返回其列表(仅python3) |
random.sample(list, 2) | 随机选取2个不重复的元素,返回其列表 |
random.random() | 随机生成0-1的随机小数,不传参 |
numpy库生成5个随机小数:
numpy.random.randn(5) # [ 0.40577836 1.11936575 -1.87445264 0.95364584 -0.29209328]
numpy.random.random(5) # [0.54716929 0.73745037 0.49771864 0.80367673 0.57557987]
1.4 time & datetime: 时间模块
方法 | 用途 |
---|---|
time.time() | 获取时间的浮点数,用于时间运算 |
time.localtime() | time.time()及time.strftime()的转化中间变量 |
time.strftime(’%Y-%m-%d %H:%M:%S’) | 获取结构化时间,如: 2021-06-01 19:45:29 |
time.strftime(’%Y-%m-%d %H:%M:%S’, time.localtime(time_a)) | 获取某个时间戳的结构化时间 |
time.sleep(5) | 暂停5s |
方法/变量 | 用途 |
---|---|
datetime.datatime.now() | 输出当前日期和时间 # 2021-06-01 19:45:29 |
datatime.date.fromtimestamp(time.time()) | 将时间戳转化为日期 |
1.5 re:正则模块
方法 | 用途 |
---|---|
re.match() | 从给定字符串的开头进行匹配,如果匹配成功就返回一个匹配对象,如果匹配不成功则返回None,使用group()方法,可以将匹配到的字符串输出。 |
re.search() | 给定字符串内查找,返回第一个匹配到的字符串。返回值类型和使用方法与match()是一样的,唯一区别就是查找的位置不用固定在文本的开头。 |
re.findall() | 给定字符串全文查找, 把所有匹配到的字符放到列表中返回。 |
re.sub() | 类似字符串的replace()方法,用指定的内容替换匹配到的字符,可以指定替换次数 |
re.sub(pattern, repl, string, count=0, flags=0) | pattern : 正则中的模式字符串。repl : 替换的字符串,也可为一个函数。string : 要被查找替换的原始字符串。count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。flags : 编译时用的匹配模式,数字形式。 |
re.compile(pattern, flags=0 ) | 将正则表达式编译成一个对象,加快速度,并重复使用 |
re.split(patten, str) | 切割字符串 |
**字符**
. 匹配除\n换行符以外的任意一个字符
\w 匹配字母、数字、下划线、汉字 例如:[A-Za-z0-9]
\s 匹配任意空白符、\t、\n、\r,re.search("\s+","ab\tc1\n3").group() 结果:\t
\d 匹配数字0-9
\b 匹配非数字
^ 匹配字符开头
$ 匹配字符结尾
**次数**
* 匹配*号前的字符0次或多次
print(re.findall('ab*','cabb3abcbbac')) #结果为['abb', 'ab', 'a']
+ 匹配+号前一个字符1次或多次
print(re.findall('ab+','ab+cd+add+bba'))#结果为['ab']
? 匹配前一个字符1次或0次
{m} 匹配前一个字符m次
{n,m} 匹配前一个字符n到m次
print(re.findall('ab{1,3}', 'abb abc abbcbb')) # 结果为['abb', 'ab', 'abb']
| 匹配|左或|右的字符
print(re.search('abc|ABC', 'ABCBabcCD').group()) # 结果为ABC
(...) 分组匹配
print(re.search("(abc){2}a(123|456)c","abcabca456c").group())#结果为abcabca456c
re.sub(r'#.*$', "", "2004-959-559#jkfdjl") # 删除注释
re.sub(r'\d+', '100', "张明 98分") # 用re.sub,将98替换为100'
re.split(r';', 'aaa bbb ccc;ddd eee,fff')
# 单字符切割,结果:['aaa bbb ccc', 'ddd eee,fff']
re.split(r'[;,]', 'aaa bbb ccc;ddd eee,fff')
# 多字符切割(需放在[]中),结果:['aaa bbb ccc', 'ddd eee', 'fff']
re.split(r'([;])', 'aaa bbb ccc;ddd eee,fff')
# 使用括号捕获分组,默认保留分割符,结果:['aaa bbb ccc', ';', 'ddd eee,fff']
re.split(r'(?:[;])', 'aaa bbb ccc;ddd eee,fff')
# 不想保留分隔符,以(?:...)的形式指定,结果:['aaa bbb ccc', 'ddd eee,fff']
# 1、正则匹配以163.com结尾的邮箱
email = ["jlkdjlk@163.com", "jkfdljfsl@163.comheihei", ".com.xiaowang@qq.com"]
for ema in email:
res = re.findall(r'@163[.]com$', ema)
print ema if res else ""
# 结果:jlkdjlk@163.com
# 2、正则匹配不是以4和7结尾的手机号
# 法1:使用match
tel = ['13994939000', '13703949394', '15893842037', '17793898888']
for te in tel:
res = re.match(r'1\d{9}[0-3,5-6,8-9]', te)
if res:
print res.group()
else:
print "tel endwith 4 or 7:", te
# 结果: 13994939000
# tel endwith 4 or 7: 13703949394
# tel endwith 4 or 7: 15893842037
# 17793898888
# 法2:使用findall
for te in tel:
res = re.findall(r'1\d{9}[0-3,5-6,8-9]', te)
if res:
print res
else:
print "tel endwith 4 or 7:", te
# 结果同上
# 3、正则匹配URL:findall结果无需加group(),search和match需要加group()提取
s = 'https://blog.csdn.net/CNdota_never_die/article/details/115863122'
print re.findall(r'https://(.*?)[.]csdn.*?11', s) # 有分组时,findall输出分组内容
# ['blog']
print re.findall(r'https://.*?[.]csdn.*?11', s) # 无分组时,输出全部
# ['https://blog.csdn.net/CNdota_never_die/article/details/11']
# match后加group()输出字符串
print re.match(r'https://.*?[.]csdn.*?11', s).group()
# 'https://blog.csdn.net/CNdota_never_die/article/details/11'
# 也可用search,同match
print re.search(r'https://.*?[.]csdn.*?11', s).group()
# 同上
# 4、匹配一个和多个
import re
s = 'xiaoming 18 years old and 1000yuan'
res = re.search(r'\d+', s).group()
# search只匹配第一个:18
res = re.findall(r'\d+', s)
# findall匹配全部:['18', '1000']
1.6 hashlib:输入任意长度,hash后输出固定长度的散列值:md5等
hashlib.md5()
import hashlib
m = hashlib.md5()
m.update('hello'.encode('utf8'))
print(m.hexdigest()) # 输出:d41d8cd98f00b204e9800998ecf8427e
2. 字典的删除键和合并
dic = {"name": 0}
# 删除键
del dic["name"] # dic为{}
# 合并字典
dic2 = {"key": 9}
dic.update(dic2) # dic为{"key": 9}
3. python实现列表去重的方法
list = [1,1,3,4,4,4,8]
print set(list) # [8, 1, 3, 4]
print [i for i in set(list)]
4. func(a, b, *arg, **kwarg)
kwargs是keyword argument的缩写,args就是argument。常见的是*args 在 **kwargs 前面。
*args是用来发送一个键值对可变数量的参数列表给一个函数,意思就是没有key值。
**kwargs将不定长度的键值对,作为参数传递给一个函数。意思就是有key值。
def this_fun(a,b,*args,**kwargs):
"""
在这个函数定义中,参数”a, b”代表”常规参数列表”。
args 接收元组作为位置参数,而非是常见的参数列表
"""
print(a,b)
print(args)
print(kwargs)
if __name__ = '__main__'
this_fun(0,1,2,3,index1=11,index2=22)
0,1
(2, 3)
{'index2': 22, 'index1': 11}
5. python2和python3的range(100)的区别
python2返回列表,python3返回迭代器,节约内存
6. 一句话解释什么样的语言能够用装饰器?
函数可以作为参数传递的语言,可以使用装饰器。
装饰器作用:将函数作为参数传给另一个函数。
python函数装饰器
def a_new_decorator(a_func):
def wrap():
print("bbb")
a_func()
print("ccc")
return wrap
@a_new_decorator
def a_func_require_decorator():
print "aaa"
a_func_require_decorator()
# 输出结果: bbb
# aaa
# ccc
7. python内建数据类型有哪些
类型 | 英文 |
---|---|
整型 | int |
布尔型 | bool |
字符串 | str |
列表 | list |
元祖 | tuple |
字典 | dict |
8. 简述面向对象中__new__和__init__区别
__init__是初始化方法,创建对象后,立刻被调用,可接收参数。__init__有一个参数self,它不需要返回值。
__new__至少有一个参数cls,代表当前类。必须要有返回值,返回实例化出来的实例(object.new(cls))或父类
class A(object):
def __init__(self, duration, thread):
self.duration = duration
self.thread = thread
def __new__(cls):
print object.__new__(cls)
return object.__new__(cls)
A()
9. with open和open
1、f=open需要f.close(),with open无需关闭
2、open读写可能出现异常,需要try来捕获
f = open("a.txt", 'w')
try:
f.write("hello")
except:
pass
finally:
f.close()
# 2
with open("a.txt", 'w') as f:
f.write("hello")
10. map()函数
map()函数根据提供的函数对指定序列做映射。第一个参数是func,第二个参数一般为list。返回包含每次 function 函数返回值的新列表。
题目:
列表[1, 2, 3, 4, 5],请使用map()函数输出[1, 4, 9, 16, 25],并使用列表推导式提取出大于10的数,最终输出[16, 25]
lis = [1, 2, 3, 4, 5]
def fn(x):
return x**2
res = map(fn, lis) # [1, 4, 9, 16, 25]
# 或者使用 lambda 匿名函数,一步即可,结果同上
res = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
res = [i for i in res if i > 10]
# res = [16, 25]
10.1 reduce()函数
先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算。
from functools import reduce
r = reduce(lambda x,y: x+y,[1,2,3,4]) #reduce函数的第一个参数是一个函数,第二个参数是一个可迭代对象
print r
#out 10
11. 避免转义给字符串加哪个字母表示原始字符串?
r , 表示需要原始字符串,不转义特殊字符
12. re正则提取
题目1:
import re
str = '<div class="nam">中国</div>'
res = re.findall(r'<div class=".*">(.*?)</div>', str)
print res
题目2:
字符串a = “not 404 found 张三 99 深圳”,每个词中间是空格,用正则过滤掉英文和数字,最终输出"张三 深圳"
代码:
import re
a = "not 404 found 张三 99 深圳"
# 匹配一位数字\d,+表示1个或多个,|表示或连接多种匹配,[a-zA-Z]表示大小写字母
res = re.findall('\d+|[a-zA-Z]+', a) # ['not', '404', 'found', '99']
for i in res:
a.replace(i,"")
# 分割多个空格
a = a.split()
print ' '.join(a) # 输出:"张三 深圳"
# ps: 匹配小数
res = re.findall('\d+\.?\d+|[a-zA-Z]+', a)
13. python中断言方法
assert()方法,断言成功,则程序继续执行;断言失败,则程序报错。
a = 7
assert(a>10)
print "assert true"
# 运行抛异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
14. 数据表student有id,name,score,city字段,其中name中的名字可有重复,需要消除重复行,请写sql语句
select distinct name from student
15. python2和python3区别?列举5个
1、python3的print为函数,需要加括号,比如 print(‘hi’)
python2 既可使用print函数,也可以使用print语句,比如 print ‘hi’
2、python2 range(1,10)返回列表,python3中返回迭代器,节约内存
3、python2中使用ascii编码,python3中使用utf-8编码
4、python2中unicode表示字符串序列,str表示字节序列
python3中str表示字符串序列,byte表示字节序列
5、python2中要正常显示中文,需引入coding声明或使用sys,python3中不需要。
python2
法1
# _*_ coding:utf-8 _*_
法2
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
6、python2中是a = raw_input()函数,python3中是a = input()函数
16. 列出python中可变数据类型和不可变数据类型,并简述原理
不可变数据类型:数值型int、字符串型string和元组tuple
不可变原理:如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象(一个地址),如下图用id()方法可以打印对象的id
a = 3
b = 3
print id(a)
print id(b)
# 结果a和b的id相同
可变数据类型:列表list和字典dict
可变原理:如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份。
a = [1, 2]
b = [1, 2]
print id(a)
print id(b)
# 结果a和b的id不同
17. 字符串去重并排序输出
题目:s = “ajldjlajfdljfddd”,去重并从小到大排序输出"adfjl"
s = "ajldjlajfdljfddd"
# 集合去重
s = set(s)
# 列表排序
s = list(s)
s.sort()
print ''.join(s)
# 输出:adfjl
18. lambda函数应用
题目1:实现两数相乘
res = lambda a,b:a*b
print res(2, 4)
# 结果:8
# map函数映射list的元素到函数
print map(lambda a:a**2, [2, 4])
print map(lambda a,b:a*b, [2, 4, 1], [3, 5, 6])
# [6, 20, 6]
题目2:对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]
res = sorted(foo, key=lambda x:x)
print res
题目3:对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]
res = sorted(foo, key=lambda x:(x<0, abs(x)))
print res
题目4:列表嵌套字典的排序,分别根据年龄和姓名排序
foo = [{“name”:“zs”,“age”:19},{“name”:“ll”,“age”:54},{“name”:“wa”,“age”:17},{“name”:“df”,“age”:23}]
key里面看成默认有个for x in list,然后选择x[‘age’]排序
foo = [{"name":"zs","age":19},{"name":"ll","age":54},{"name":"wa","age":17},{"name":"df","age":23}]
print sorted(foo, key=lambda x:x['age'])
# 年龄排序结果:[{'age': 17, 'name': 'wa'}, {'age': 19, 'name': 'zs'}, {'age': 23, 'name': 'df'}, {'age': 54, 'name': 'll'}]
print sorted(foo, key=lambda x:x['name'])
# 姓名排序结果:[{'age': 23, 'name': 'df'}, {'age': 54, 'name': 'll'}, {'age': 17, 'name': 'wa'}, {'age': 19, 'name': 'zs'}]
题目5:列表嵌套元组,分别按字母和数字排序
foo = [("zs", 19), ("ll", 54), ("wa", 17), ("df", 23)]
print sorted(foo, key=lambda x:x[0])
# 按字母升序:[('df', 23), ('ll', 54), ('wa', 17), ('zs', 19)]
print sorted(foo, key=lambda x:x[1])
# 按数字升序:[('wa', 17), ('zs', 19), ('df', 23), ('ll', 54)]
题目6:列表嵌套元祖排序,年龄数字相同怎么办?
两个条件
foo = [("zs", 23), ("ll", 23), ("wa", 17), ("df", 23)]
print sorted(foo, key=lambda x:(x[1],x[0]))
# [('wa', 17), ('df', 23), ('ll', 23), ('zs', 23)]
题目7:字典按键排序
foo = {"name":"zs","age":19,"city":"beijing"}
# 先转化成列表
print foo.items()
# [('city', 'beijing'), ('age', 19), ('name', 'zs')]
res = sorted(foo.items(), key=lambda x:x[0])
print res
# [('age', 19), ('city', 'beijing'), ('name', 'zs')]
题目8:根据字符串长度排序
s = ["ab", "abs", "j", "kldjsl"]
b = sorted(s, key=lambda x:len(x))
print b
# ['j', 'ab', 'abs', 'kldjsl']
s.sort(key=len)
print s
['j', 'ab', 'abs', 'kldjsl']
题目9:修改list值,匿名函数简洁
a = ["beijing", "China", "", "happy", "1"]
print map(lambda x:"push" if x=="" else x, a)
# ['beijing', 'China', 'push', 'happy', '1']
19. 字典根据键从小到大排序
题目:dic={“name”:“zs”,“age”:18,“city”:“深圳”,“tel”:“1362626627”}
字典其实是无序的,此题有点问题。可排序成list。
dic={"name":"zs","age":18,"city":"Beijing","tel":"1362626627"}
list = dic.items()
# [('city', 'Beijing'), ('age', 18), ('tel', '1362626627'), ('name', 'zs')]
# 按键的首字母排序
list.sort(key=lambda i:i[0])
# [('age', 18), ('city', 'Beijing'), ('name', 'zs'), ('tel', '1362626627')]
# 转化为字典
print dict(list)
# {'city': 'Beijing', 'age': 18, 'tel': '1362626627', 'name': 'zs'}
20. 利用collections库的Counter方法统计字符串每个单词出现的次数
题目:str = “kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h”
from collections import Counter
str = "jalfj;ldsjafl;dsl"
print Counter(str)
# 生成字典,结果:Counter({'l': 4, 'j': 3, 'a': 2, 'd': 2, 'f': 2, 's': 2, ';': 2})
# 可取其中一个字符,打印其次数
print Counter(str)['j']
20.1 统计字符串中某个字符出现的次数
str = "kjalfj;ldsjafl;hdsl"
print str.count('j')
# 结果:5
21. filter方法求出列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
filter(function, iterable)
filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
该函数接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def is_odd(m):
return True if m % 2 == 1 else False
new_list = filter(is_odd, a)
print new_list
# 结果:[1, 3, 5, 7, 9]
# 法二:列表推导式求新列表
new_list = [i for i in a if i % 2 == 1]
22. 数据库优化查询方法
外键、索引、联合查询、选择特定字段等
23. 请列出你会的任意一种统计图(条形图、折线图等)绘制的开源库,第三方也行
pychart、matplotlib
24. 正则表达式匹配中,(.)和(.?)匹配区别?
(.*)是贪婪匹配,会把满足正则的尽可能多的往后匹配,任意次
(.*?)是非贪婪匹配,会把满足正则的尽可能少匹配,1或0次
25. [[1,2],[3,4],[5,6]]一行代码展开该列表,得出[1,2,3,4,5,6]
# 法1:列表推导式
a = [[1, 2], [3, 4], [5, 6]]
print [j for i in a for j in i]
# [1, 2, 3, 4, 5, 6]
# 法2:将列表转成numpy矩阵,通过numpy的flatten()方法,再将数组array转化成list
import numpy
print numpy.array(a).flattern().tolist()
26. 异常模块中try except else finally的相关意义
try…except…else没有捕获到异常,执行else语句
try…except…finally不管是否捕获到异常,都执行finally语句
27. 说明zip()函数用法
>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b) # 打包为元组的列表
[(1, 4), (2, 5), (3, 6)]
>>> zip(a,c) # 元素个数与最短的列表一致
[(1, 4), (2, 5), (3, 6)]
>>> zip(*zipped) # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式
[(1, 2, 3), (4, 5, 6)]
28. 写5条常用sql语句
show databases; # 查看数据库
use test; # 使用test数据库
show tables; # 查看表
desc 表名; # 查看表结构
select * from 表名; # 单表全字段查询
select * from t1 where socre>90; # 单表条件查询
delete from 表名 where id=5; # 删除
update students set gender=0,hometown="北京" where id=5 # 更新。语法:update 表名 set 更改的字段名=值 where 条件;
29. 提高python运行效率的方法
1、使用生成器,因为可以节约大量内存
2、循环代码优化,避免过多重复代码的执行
3、核心模块用Cython PyPy等,提高效率
4、多进程、多线程、协程
5、多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率
30. 简述mysql和redis区别
redis: 内存型非关系数据库,数据保存在内存中,速度快
mysql:关系型数据库,数据保存在磁盘中,检索的话,会有一定的Io操作,访问速度相对慢
31. 对列表进行排序,不能用sort
list=[2,3,5,4,9,6],从小到大排序,不许用sort,输出[2,3,4,5,6,9]
利用min()方法求出最小值,原列表删除最小值,新列表加入最小值,递归调用获取最小值的函数,反复操作
list1=[2,3,5,4,9,6]
new_list = []
def get_min(list1):
min1 = min(list1)
list1.remove(min1)
new_list.append(min1)
if len(list1) > 0:
get_min(list1)
return new_list
new_list = get_min(list1)
print new_list
# [2, 3, 4, 5, 6, 9]
32. 写一个单例模式
因为创建对象时__new__方法执行,并且必须return返回实例化出来的对象cls.__instance是否存在,不存在的话就创建对象,存在的话就返回该对象,来保证只有一个实例对象存在(单例),打印ID,值一样,说明对象为同一个。
class Singleton(object):
__instance = None
def __new__(cls, name, age):
# 若类属性__instance为None,则创建一个对象,并赋值为这个对象的引用,
# 下次调用时就知道之前已经创建过这个对象,保证只有1个对象。
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
a = Singleton("dog", 10)
b = Singleton("cat", 8)
print id(a)
print id(b)
# 结果:两个地址相同,证明指向同一个对象
a.age = 19
print b.age #
# 结果:19
33. 列出常见的状态码和意义
2xx (成功)表示成功处理了请求的状态代码。
3xx (重定向)表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
4xx(请求错误) 这些状态代码表示请求可能出错,妨碍了服务器的处理。
5xx(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
状态码 | 英文 | 含义 |
---|---|---|
200 | OK | (成功) 服务器已成功处理了请求。 |
204 | No Content | (无内容) 服务器成功处理了请求,但没有返回任何内容。 |
206 | Partial Content | (部分内容) 服务器成功处理了部分 GET 请求 |
301 | Moved Permanently | (永久重定向)资源已永久分配新URI |
302 | Found | 临时重定向,资源已临时分配新URI |
303 | See Other | 临时重定向,期望使用GET定向获取 |
304 | Not Modified | 发送的附带条件请求未满足 |
307 | Temporary Redirect | 临时重定向,POST不会变成GET |
400 | Bad Request | 请求报文语法错误或参数错误 |
401 | Unauthorized | 需要通过HTTP认证,或认证失败 |
403 | Forbidden | 请求资源被拒绝 |
404 | Not Found | 无法找到请求资源(服务器无理由拒绝) |
500 | Internal Server Error | 服务器故障或Web应用故障 |
503 | Service Unavailable | 服务器超负载或停机维护 |
34. 使用pop和del删除字典中键值
题目:删除字典中的"name"字段
dic={"name":"zs","age":18}
del dic["name"]
dic={"name":"zs","age":18}
dic.pop("name")
# 结果都为{"age": 18}
35. 简述cookie和session的区别
Cookie和Session的使用详解
Cookie方式请求响应过程:
步骤1:我们访问浏览器的时候,浏览器会发送一个HTTP请求到服务器端;
步骤2:服务器会发送一个HTTP响应到客户端,其中包括Sst-Cookie,意思就是浏览器建立一个cookie保存服务器指定的内容,比如用户信息和用户操作信息;
步骤3:浏览器保存好信息之后,下次我们再次访问网站的时候,浏览器再发送HTTP请求到服务器端时都会携带之前保存的cookie;
步骤4:服务器端会从收到的cookie中识别用户身份,就能让页面为你提供专门属于你的内容了。
Session方式过程:
1、客户端浏览器访问网站
2、服务器会向客户浏览器发送一个每个用户特有的会话编号sessionID,让他进入到cookie里。服务器同时也把sessionID和对应的用户信息、用户操作记录在服务器上,这些记录就是session。
3、客户端浏览器再次访问时,会发送cookie给服务器,其中就包含sessionID。
4、服务器从cookie里找到sessionID,再根据sessionID找到以前记录的用户信息就可以知道他之前操控些、访问过哪里。
session保存在服务器端比较安全,但是可能需要记录千百万用户的信息,对服务器的存储压力很大,所以我们应该有选择的合理使用cookie和session。
1、session 在服务器端,cookie 在客户端(浏览器)
2、session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效,存储Session时,键与Cookie中的session id相同,值是开发人员设置的键值对信息,进行了base64编码,过期时间由开发人员设置
3、cookie安全性比session差,cookie存储在用户浏览器里不安全,任何人都能直接查看(右键检查或F12即可)。
36. 简述多线程、多进程
进程:
1、操作系统进行资源分配和调度的基本单位,多个进程之间相互独立。
2、稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制。
线程:
1、CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程的所有资源。
2、如果IO操作密集,则可以多线程运行效率高,缺点是如果一个线程崩溃,都会造成进程的崩溃。
应用:
IO密集的用多线程,在用户输入,sleep 时候,可以切换到其他线程执行,减少等待的时间。
CPU密集的用多进程,因为假如IO操作少,用多线程的话,因为线程共享一个全局解释器锁,当前运行的线程会霸占GIL,其他线程没有GIL,就不能充分利用多核CPU的优势。
37. IOError、AttributeError、ImportError、IndentationError、IndexError、KeyError、SyntaxError、NameError分别代表什么异常
IOError:输入输出异常
AttributeError:试图访问一个对象没有的属性
ImportError:无法引入模块或包,基本是路径问题
IndentationError:语法错误,代码没有正确的对齐
IndexError:下标索引超出序列边界
KeyError:试图访问你字典里不存在的键
SyntaxError:Python代码逻辑语法出错,不能执行
NameError:使用一个还未赋予对象的变量
38. python中copy和deepcopy区别
参考:浅拷贝和深拷贝图解
1、复制不可变数据类型,不管copy还是deepcopy,都是同一个地址当浅复制的值是不可变对象(数值,字符串,元组)时和=“赋值”的情况一样,对象的id值与浅复制原来的值相同。
import copy
a = "abxx"
b = copy.copy(a)
c = copy.deepcopy(a)
# b c 的id和值均相同
浅拷贝copy有两种情况:
第一种情况:复制的 对象中无 复杂 子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。
第二种情况:复制的对象中有 复杂 子对象 (例如列表中的一个子元素是一个列表), 改变原来的值 中的复杂子对象的值 ,会影响浅复制的值。
深拷贝deepcopy:完全复制独立,包括内层列表和字典
39. 列出几种魔法方法并简要介绍用途
init:对象初始化方法
new:创建对象时候执行的方法,单例模式会用到
str:当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据
del:删除对象执行的方法
40. 迭代器
yield函数解释
yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。带yield的函数才是真正的迭代器。
41. 列表推导式、字典推导式、生成器
# 列表推导式
import random
td_list = [i for i in range(10)]
print td_list, type(td_list)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <type 'list'>
# 字典推导式
dic = {k: random.randint(1,5) for k in ["a", "b", "c", "d"]}
print dic, type(dic)
# {'a': 4, 'c': 5, 'b': 4, 'd': 2} <type 'dict'>
# 生成器
gen = (i for i in range(10))
print gen, type(gen)
# <generator object <genexpr> at 0x7f58c3e320f0> <type 'generator'>
42. 递归求和
def sum(num):
if num >= 1:
res = num + sum(num-1)
else:
res = 0
return res
print sum(10)
# 结果:55
43. 简述python引用计数机制
python垃圾回收主要以引用计数为主,标记-清除和分代清除为辅的机制,其中标记-清除和分代回收主要是为了处理循环引用的难题。
引用计数算法:
当有1个变量保存了对象的引用时,此对象的引用计数就会加1。
当使用del删除变量指向的对象时,如果对象的引用计数不为1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除。
class Animal(object):
def __init__(self, name):
print "__init__ called"
self.__name = name
# Python __del__()方法:销毁对象
def __del__(self):
print "__del__ called"
print "%s is removed." % self.__name
cat = Animal("Lucy") # 调用__init__函数
print "aaaa"
cat2 = cat
print "bbbb"
cat3 = cat # 此时引用计数为3
# cat cat2 cat3
del cat # 引用计数为2
print "ccc"
del cat2 # 引用计数为1
print "ddd"
del cat3 # 引用计数为0,最后一次删除,会调用__del__函数
print "eee"
# 结果:__init__ called
# aaaa
# bbbb
# ccc
# ddd
# __del__ called
# Lucy is removed once.
# eee
44. 简述乐观锁和悲观锁
在秒杀系统中,为什么可以使用乐观锁解决超卖问题而不能使用悲观锁呢?
参考:悲观锁和乐观锁
悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁。
乐观锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,乐观锁实现的2种方式:版本号机制和时间戳机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。
45. r、w读写模式
r 只读
w 写,覆盖原文件
r+ 读写
w+ 读写,覆盖原文件
a+ 读写,追加到原文件
46. 两个list的交集并集
a = [1, 2, 3, 4]
b = [4, 3, 5, 6]
jj = [i for i in a if i in b]
# [3, 4]
jj2 = list(set(a).intersection(set(b)))
# [3, 4]
bj = list(set(a).union(set(b)))
# [1, 2, 3, 4, 5, 6]
cj = list(set(a).difference(set(b))) # a中有,b中没有
# [1, 2]
cj2 = list(set(b).difference(set(a))) # b中有,a中没有
# [5, 6]
47. 常见的网络传输协议
UDP、TCP、FTP、HTTP、SMTP等
48. HTTP请求中get和post区别
1、GET请求是通过URL直接请求数据,数据信息可以在URL中直接看到,比如浏览器访问;而POST请求是放在请求头中的,我们是无法直接看到的;
2、GET提交有数据大小的限制,一般是不超过1024个字节。少量的数据使用GET,大量的数据使用POST。
3、GET请求因为数据参数是暴露在URL中的,所以安全性比较低,比如密码是不能暴露的,就不能使用GET请求;POST请求中,请求参数信息是放在请求头的,所以安全性较高,可以使用。在实际中,涉及到登录操作的时候,尽量使用HTTPS请求,安全性更好。
49. python中读取Excel文件的方法
1、应用数据分析库pandas
import pandas
print pandas.read_excel('./query.xlsx')
# 打印表格内容
2、xlrd库解析xlsx表格
import xlrd
data = xlrd.open_workbook("./query.xlsx") # 打开当前目录下名为query.xlsx的文档
# 此时data相当于指向该文件的指针
table = data.sheet_by_index(0) # 通过索引获取,打开第一个sheet表格
table = data.sheet_by_name("sheet1") # 通过名称获取,读取sheet1表格 【常用】
table = data.sheets()[0] # 通过索引顺序获取
# 以上三个函数都会返回一个xlrd.sheet.Sheet()对象,三选一使用
# 1.对行进行操作
table.row(2) # 返回第二行所有单元格对象组成的列表
table.row_values(1) # 返回第一行所有单元格数据
# 2. 对列进行操作
table.col(1) # 返回第一列所有单元格对象组成的列表
table.col_values(2) # 返回第2列所有单元格数据
# 3. 对单元格进行操作
table.cell_value(1, 2) # 返回第一行第二列单元格数据 【常用】
50. 简述多线程、多进程
进程:
1、操作系统进行资源分配和调度的基本单位,多个进程之间相互独立
2、稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制
线程:
1、CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程的所有资源
2、如果IO操作密集,则可以多线程运行效率高,缺点是如果一个线程崩溃,都会造成进程的崩溃
应用:
IO密集的用多线程。在用户输入,sleep 时候,可以切换到其他线程执行,减少等待的时间。当前线程发出请求后,由于不占用cpu资源,可以阻塞等待,然后cpu执行权可以被另外一个线程所享有去发网络请求。IO密集型,单个CPU利用率很低,可能只有10%,所以多线程可以提升cpu利用率,可能10个线程才能打满一个核心, 从而多线程也有并行的效果。
CPU密集的用多进程。python的多线程只能使用一个cpu核心,io密集型应用,本来cpu占用率就很低,单个cpu核心就够了。用多进程给它多几个核心也不能提升性能。cpu密集型的,显然只用一个cpu核心是不行的。
解释:
IO密集是涉及到网络、磁盘的任务,其消耗CPU资源少,任务的大部分时间都在等待IO操作完成,如Web应用。
CPU密集是指需要CPU计算能力的任务,如视频处理等。
IO密集型,大部分时间在处理I/O请求,不需要CPU提供多大算力,这是后频繁切换可以提高并发性,所以I/O密集型的处理,希望在高并发下进行,多线程并发消耗资源少。
CPU密集型,占用CPU算力大,希望能获得更长的时间轮片而不是经常切换;这样使用进程较好,进程本身优于线程,只是切换调度消耗的资源多。
51. post的编码方式
参考:post的4种编码方式
enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。
Content-Type
enctype | 作用 |
---|---|
application/x-www-form-urlencoded | 默认,浏览器的原生 form 表单, key1=value1&key2=value2 |
multipart/form-data | 一般用于表单需要文件上传 |
application/json | 传递文本内容,消息主体是序列化后的 JSON 字符串 |
text/xml | XML 作为编码方式的远程调用规范 |
52. 长链接和短连接
1、HTTP短连接(非持久连接)是指客户端收到服务端的响应后,立刻发送FIN消息,主动释放连接。也有服务端主动断连的情况。客户端和服务端进行一次HTTP请求/响应之后,就关闭连接。所以,下一次的HTTP请求/响应操作就需要重新建立连接。
注:短连接是建立在TCP协议上的,有完整的握手挥手流程,区别于UDP协议。
2、HTTP长连接(持久连接)是指,在TCP层握手成功后,不立即断开连接,并在此连接的基础上进行多次消息(包括心跳)交互,直至连接的任意一方(客户端OR服务端)主动断开连接,此过程称为一次完整的长连接。客户端和服务端建立一次连接之后,可以在这条连接上进行多次请求/响应操作。持久连接可以设置过期时间,也可以不设置。
HTTP/1.0 默认短连接,HTTP/1.1起,默认长连接。
连接类型 | 设置 |
---|---|
设置HTTP短连接 | 在首部字段中设置Connection:close,则在一次请求/响应之后,就会关闭连接。 |
设置HTTP长连接,有过期时间 | 在首部字段中设置Connection:keep-alive 和Keep-Alive: timeout=60 |
设置HTTP长连接,无过期时间 | 在首部字段中只设置Connection:keep-alive,表明连接永久有效。 |
3、什么时候用长连接,短连接?1、需要频繁交互的场景使用长连接,如即时通信工具(微信/QQ,QQ也有UDP),相反则使用短连接,比如普通的web网站,只有当浏览器发起请求时才会建立连接,服务器返回相应后,连接立即断开。2、维持长连接会有一定的系统开销,用户量少不容易看出系统瓶颈,一旦用户量上去了,就很有可能把服务器资源(内存/CPU/网卡)耗尽,所以使用需谨慎。
53. http协议
参考:http协议详解
HTTP 请求/响应的步骤:
\1. 客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://www.baidu.com。
\2. 发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
\3. 服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
\4. 释放连接TCP连接
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
\5. 客户端浏览器解析HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
在浏览器地址栏键入URL,按下回车之后会经历以下流程:
1·、浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
2、解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;
3、浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
4、服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
5、释放 TCP连接;
6、浏览器将该 html 文本并显示内容;
54. int占几个字节
在32位机器和64位机器中int类型都占用4个字节。float也占4个字节。
55. 应用层基于TCP和UDP的协议
1.基于TCP的应用层协议有:HTTP、FTP、SMTP、TELNET、SSH
2.基于UDP的应用层协议:DNS、TFTP(简单文件传输协议)、SNMP:简单网络管理协议
56. 五种进程调度算法
1、时间片轮转调度算法(RR):给每个进程固定的执行时间,根据进程到达的先后顺序让进程在单位时间片内执行,执行完成后便调度下一个进程执行,时间片轮转调度不考虑进程等待时间和执行时间,属于抢占式调度。优点是兼顾长短作业;缺点是平均等待时间较长,上下文切换较费时。适用于分时系统。
2、先来先服务调度算法(FCFS):根据进程到达的先后顺序执行进程,不考虑等待时间和执行时间,会产生饥饿现象。属于非抢占式调度,优点是公平,实现简单;缺点是不利于短作业。
3、优先级调度算法(HPF):在进程等待队列中选择优先级最高的来执行。
4、多级反馈队列调度算法:将时间片轮转与优先级调度相结合,把进程按优先级分成不同的队列,先按优先级调度,优先级相同的,按时间片轮转。优点是兼顾长短作业,有较好的响应时间,可行性强,适用于各种作业环境。
5、高响应比优先调度算法:根据“响应比=(进程执行时间+进程等待时间)/ 进程执行时间”这个公式得到的响应比来进行调度。高响应比优先算法在等待时间相同的情况下,作业执行的时间越短,响应比越高,满足段任务优先,同时响应比会随着等待时间增加而变大,优先级会提高,能够避免饥饿现象。优点是兼顾长短作业,缺点是计算响应比开销大,适用于批处理系统。
57. 常见的数据结构
数据结构分为8类有:数组、栈、队列、链表、树、散列表、堆、图。
数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成 。