python面试题-110道
用一行代码实现1-101的总和
sum(range(1, 101))
在函数中改变全局变量的值
i = 111
def func():
global i
i += 100
列出五个标准库
-- re
-- time
-- json
-- subprocess
-- random
字典如何删除键和合并俩个字典
del user_info['k1']
dic.update(user_info)
谈下python的GIL
# GIL不是python的而是cpython的
# GIL是因为cpython的Gc垃圾回收机制导致的,一把全局解释器锁
# 它保护的是全局的值不会出现刚要赋值建立计数的时候,垃圾回收机制给回收了,发现值找到了而变量没了.
# 当然,加了这把锁不意味着你的python程序中的数据安全就不需要加锁了.
# 当然这也就导致了同一个python程序中的多个线程同一时间只能有一个线程在工作.
"""
GIL 是cpython的全局解释器锁,同一进程中假如有多个线程运行,一个线程在运行python程序的时候会霸占python解释器(加了一把锁即GIL),使该进程内的其他线程无法运行,等该线程运行完后其他线程才能运行。如果线程运行过程中遇到耗时操作,则解释器锁解开,使其他线程运行。所以在多线程中,线程的运行仍是有先后顺序的,并不是同时进行。
多进程中因为每个进程都能被系统分配资源,相当于每个进程有了一个python解释器,所以多进程可以实现多个进程的同时运行,缺点是进程系统资源开销大
"""
python实现列表去重的方法
l1 = [1, 3, 4, 3, 3, 4, 5, 6, 6, 7]
li1 = []
for i in l1:
if i not in li1:
li1.append(i)
l1 = li1
print(l1)
# 方式2
l1 = set(l1)
l1 = [x for x in l1]
func(*args,**kwargs)中的*args,**kwargs什么意思?
"""
*args 如果是形参的话,*是用来接收多余的位置实参,合并在一起,为一个元组的格式赋值给args;而为实参时,则是打散功能,将args小元组内的值打散成一个个的元素当作位置形参
**kwargs 如果是形参的话,它是用来接收多余的关键字实参,为一个字典的格式赋值给其后的kwargs.而为实参时,则是打散功能,将小元组内的值打散成一个个的key=value默认形参
"""
python2和python3的range(100)的区别
"""
python2 中的range(100) 是先创建了一个0-99的列表
而python3中的range(100) 是先产生了一个迭代器里面可以产生0-99个值,然后要值得时候就产生一个,不会和python2中一样产生一个很大的列表占内存
"""
一句话解释什么样的语言能够用装饰器?
"""
函数可以作为参数传递的语言
"""
python内建数据类型有哪些
"""
int
float
boll
str
list
tuple
set
dict
"""
简述面向对象中__new__和__init__区别
"""
__new__ 是实例化了一个类对象,里面必须有一个参数cls,而且必须要有返回值
__init__ 是指的是类的起始数据,由该类实例化的对象加载的起始数据
"""
"""
答案:
1、__new__至少要有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别
2、__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类(通过super(当前类名, cls))__new__出来的实例,或者直接是object的__new__出来的实例
3、__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值
4、如果__new__创建的是当前类的实例,会自动调用__init__函数,通过return语句里面调用的__new__函数的第一个参数是cls来保证是当前类实例,如果是其他类的类名,;那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__函数,也不会调用其他类的__init__函数。
"""
简述with方法打开处理文件帮我我们做了什么?
"""
with open():
即上下文文件管理
即会帮我们在打开完文件进行读/写操作之后,会自动帮我们将open内的文件资源回收
不需要我们手动的通过f.close()去关闭f这个对象.
而是python会帮我们回收掉f这个对象的资源
"""
列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]
map()函数第一个参数是fun,第二个参数是一般是list,第三个参数可以写list,也可以不写,根据需求
l = [j for j in list(map(lambda num:num**2, [1,2,3,4,5])) if j > 10]
print(l)
14、python中生成随机整数、随机小数、0--1之间小数方法
import random
# 随机整数
print(random.randint(1,10))
print(random.randrange(1,10,2))
print(random.getrandbits(9))
# 随机小数
print(random.random()) # 0-1之间的小数
print(random.uniform(1,10))
# numpy 模块
import numpy as np
# nnumpy模块随机产生n个小数
print(np.random.randn(3)) # 随机产生3个小数 包括正负小数
15、避免转义给字符串加哪个字母表示原始字符串?
"""
为了避免/在python中的特殊语义,可以在/前面加一个/
如果是字符串类型的需要转义还可以使用
r"/root/..." r表示字符串内的字符为原生字符
"""
16、<div class="nam">中国</div>
,用正则匹配出标签里面的内容(“中国”),其中class的类名是不确定的
import re
re_str = '<div class="nam">中国</div>'
reg = 'class.*?>(.*?)<'
print(re.findall(reg,re_str))
python中断言方法举例
li = [1,3,3,4]
if len(li) < 3:
raise Exception('列表长度小于3')
assert len(li) > 3
print("列表的长度大于3,断言成功")
18、数据表student有id,name,score,city字段,其中name中的名字可有重复,需要消除重复行,请写sql语句
select distinct name from student;
create table student(
id int primary key auto_increment,
name varchar(24),
score int,
city varchar(16)
);
insert into student values
(1,"jkey",10,"china"),
(2,"jkey2",10,"china"),
(3,"jkey",10,"china"),
(4,"jkey1",10,"china"),
(5,"jkey2",10,"china"),
(6,"jkey3",10,"china");
select distinct name from student;
create table student1(
id int primary key,
name varchar(24),
score int,
city varchar(16)
);
insert into student1(id,name,score,city) select * from student where name in (select name from student group by name having count(id) =1);
insert into student1(id,name,score,city) select * from student where name in (select name,count(name) as nn from student group by name having count(id) >1) as t1 limit t1.nn;
select * from student where id in (select name from student);
19、10个Linux常用命令
"""
cd ../.. 切换目录
vim a.txt 编辑文件
cat a.txt 查询文件
more a.txt 查看文件
tasklist 查看进程
taskkill -9 xxx 杀死进程
find xx | grep 'x' 在xx中过滤出x
echo 打印
ifconfig 显示网络配置信息
ping ip
ssh ...
telnet ...
makdir 创建目录
rm -rf 递归强制删除
cp x xx copy x到xx
scp 跨服务器copy
chmod 777 xxx改权限
pwd 显示当前目录
touch 没有就创建一个目录
"""
python2和python3区别?列举5个
"""
1. range(100) python2中产生的是0-99的列表,而python3中产生的是一个迭代器,可以产生0-99的值的迭代器
2. 经典类和新式类 python2 没有继承object的类叫做经典类,而python3中所有的类都是新式类,只要调用的类中的c3列表中有object类即可
3.python2中默认使用acsii字符编码,而python3中默认使用utf-8字符编码
4.python2中unicode表示字符串序列,str表示字节序列
python3中str表示字符串序列,byte表示字节序列
5. python2中的交互方法有raw_input(),而python3中只有input()交互方法
6. Python3 使用 print 必须要以小括号包裹打印内容,比如 print('hi')
Python2 既可以使用带小括号的方式,也可以使用一个空格来分隔打印内容,比如 print 'hi'
7. python2中为正常显示中文,引入coding声明,python3中不需要
"""
列出python中可变数据类型和不可变数据类型,并简述原理
"""
可变数据类型
list
dict
set
不可变数据类型
int/float
str
tuple
boll
"""
# 不可变数据类型,因为如果改变了类型的值,就相当于重新实例化了一个对象,而对于相同值得对象.在内存中只能有一个对象(一个地址),使用id()方法即可查看变量的内存地址
# 可变数据类型中示例化的对象内置都有append()或者=赋值的方法,所以它们不会实例化出一个新的对象,即不用再开辟内存地址,所以可以进行添加和删除值.
22、s = "ajldjlajfdljfddd",去重并从小到大排序输出"adfjl"
s = "ajldjlajfdljfddd"
print("".join(list(sorted(set(list(s))))))
print("".join(list(sorted(set(s)))))
print("".join(sorted(set(s))))
23、用lambda函数实现两个数相乘
res = lambda x,y:x*y
print(res(2,4))
24、字典根据键从小到大排序
dic={"name":"jkey","age":18,"city":"上海","tel":"18718733543"}
dic={"name":"jkey","age":18,"city":"上海","tel":"18718733543"}
print(sorted(dic,key=lambda k:str(dic[k])))
25、利用collections库的Counter方法统计字符串每个字母出现的次数"kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h"
from collections import Counter
s = "kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h"
print(Counter(s)) # Counter({'l': 9, ';': 6, 'h': 6, 'f': 5, 'a': 4, 'j': 3, 'd': 3, 's': 2, 'k': 1, 'g': 1, 'b': 1})
26、字符串a = "not 404 found 张三 99 深圳",每个词中间是空格,用正则过滤掉英文和数字,最终输出"张三 深圳"
import re
a = "not 13.14 a_1 }}4}}41 $ ^ 404 found 张三 99 深圳"
# 方法1 直接通过匹配中文在unicode表中的字符
reg = r"[\u4e00-\u9fa5]+"
li = re.findall(reg, a)
print(" ".join(li))
# 方式2 通过列表除值
s_li = a.split(' ')
reg = r"[0-9a-zA-Z_.$^}]+" # 这就让字符里面有什么就往[]中加什么即可, 不够灵活.
re_li = re.findall(reg, a)
for i in re_li:
if i in s_li:
s_li.remove(i)
print(" ".join(s_li))
27、filter方法求出列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(list(filter(lambda x:x%2!=0,a)))
28、列表推导式求列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(list(i for i in a if i%2!=0))
29、正则re.complie作用
"""
complie() 方法可以将字符串用正则匹配的对象保存起来,下次使用时就不要再写re匹配代码了.
pattern = re.complie(pattern[,flag]) 其中的参数pattern是一个正则表达式,后面的flag是一个匹配模式 比如 匹配忽略大小写.
而单个的pattern是没有意义的,它可以直接调用re下面的匹配方法,如search,findall..等方法一起使用,则就不需要传第一个正则表达式到方法中,只需要填写一个字符串即可.
这样做的好处是保存了正则表达式,加快了查询速度,是先创建了正则表达式对象,再去匹配.
"""
30、a=(1,)b=(1),c=("1") 分别是什么类型的数据?
"""
a是一个元组类型的数据类型;
b是一个整型
c是一个字符串
"""
31、两个列表[1,5,7,9]和[2,2,6,8]合并为[1,2,2,3,6,7,8,9]
l1 = [1,5,7,9]
l2 = [2,2,6,8]
l1.extend(l2)
print(l1)
l3 = l1+l2
print(type(l3))
l3.sort() # sort() 返回的是一个none,即没有返回值
print(l3)
l3 = sorted(l3) # sorted返回的是一个列表,即可以重新赋值
print(l3)
32、用python删除文件和用linux命令删除文件方法
python: os.remove(a.txt)
linux: rm -rf a.txt
33、log日志中,我们需要用时间戳记录error,warning等的发生时间,请用datetime模块打印当前时间戳 “*2018-04-01 11:38:54*”
import datetime
print(datetime.datetime.now().strftime("%Y-%m-%d %X"))
34、数据库优化查询方法
-- 可以创建索引
-- 但是创建索引的前提是查询时要命中索引
-- 索引一般将区分度高的和字段名小的(索引值小,一个页面放的节点就多了,B+树就低了,查询就快了)
35、请列出你会的任意一种统计图(条形图、折线图等)绘制的开源库,第三方也行
matplotlib 模块 pychart模块
36、写一段自定义异常代码
class MyRaise():
def __init__(self, name, age):
if not isinstance(name,str):
raise TypeError("名字必须为字符串类型")
if not isinstance(age, int):
raise TypeError("年龄必须为整数")
self.name = name
self.age = age
m = MyRaise('jkey', 1.1) # 抛异常
37、正则表达式匹配中,(.)和(.?)匹配区别?
"""
(.) 是一个贪婪匹配,它会匹配到最后一个符合
(.?) 是一个非贪婪的匹配,它会匹配到第一个符合的就停止匹配了
"""
38、简述Django的orm
"""
orm是一个管理数据库的第三方软件
是为了让只学习了python的程序员也可以使用很好的管理数据库
不用去学习原生的sql语句
大大提升了程序员的开发效率
程序员不仅可以开发业务逻辑,也可以管理数据库,减少了俩个部门之间的沟通性.
"""
-
[[1,2],[3,4],[5,6]]一行代码展开该列表,得出[1,2,3,4,5,6]
l1 = [[1, 2], [3, 4], [5, 6]]
l2 = []
for i in l1:
for j in i:
l2.append(j)
print(l2)
print(list((j for i in l1 for j in i)))
# numpy
import numpy as np
l = np.array(l1).flatten().tolist()
print(l)
40、x="abc",y="def",z=["d","e","f"],分别求出x.join(y)和x.join(z)返回的结果
x = "abc"
y = "def"
z = ["d","e","f"]
print(x.join(y)) # ---> dabcdeabcf
print(x.join(z)) # ---> dabceabcf
41、举例说明异常模块中try except else finally的相关意义
try:
被监测的代码1
被监测的代码2
except 错误类型1 as e:
处理代码1
except (错误类型2,错误类型3) as e:
处理该类型异常代码2
except Exception as e:
处理万能异常代码
else:
被监测的代码没有异常时执行的代码
finally:
无论被检查代码有无异常都执行,一般做系统回收资源操作
42、python中交换两个数值
z = 1
c = 2
c,z = z,c
print(z,c)
43、举例说明zip()函数用法
"""
zip([iterables]) 方法
- 功能: 将可迭代对象打包成一个个的元组的对象,可以通过list()方法查看这个对象中的值
- 参数: iterables: 迭代器对象.可以是一个.也可以是多个
- 它会将每个迭代器对象对应的索引组成一个元组,该元组由最短的迭代器对象确认有几个元组
"""
# 例如:迭代器长度一样
a = [1,2,3]
b = [4,5,6]
c = [7,8,9]
print(list(zip(a,b,c))) # [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
x = [1,2,3]
y = [4,5]
z = [6]
print(list(zip(x,y,z))) # [(1,4,6)]
# zip(*zip) 可以取回迭代器对象,但是都变成了元组
x,y,z = zip(*zip(x,y,z))
44、a="张明 98分",用re.sub,将98替换为100
import re
a="张明 98分"
re.sub("\d+","100",a)
45、写5条常用sql语句
create table t666(
id int primary key auto_increment,
name varchar(24) not null,
age int default 18
);
insert into t666(name,age) values
('jkey',18),
("刘大傻",38);
select * from t666;
select name from t666 where id=2;
delete from t666 where id=1;
46、a="hello"和b="你好"编码成bytes类型
a = "hello"
b = "你好"
a = b'hello'
b_2 = b.encode('utf-8')
print(type(a),type(b_2))
47、[1,2,3]+[4,5,6]的结果是多少?
"""变成一个大列表,会进行列表合并的操作"""
l1 = [1,2,3]
l2 = [4,5,6]
print(l1+l2)
[1,2,3,4,5,6]
48、提高python运行效率的方法
"""
1、使用生成器,因为可以节约大量内存
2、循环代码优化,避免过多重复代码的执行
3、核心模块用Cython PyPy等,提高效率
4、多进程、多线程、协程
5、多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率
"""
49、简述mysql和redis区别
"""
mysql 是一种关系型数据库,它的主要工作是将用户的全部信息数据存到数据库,它更偏重于硬盘,因此它的传输效率是比不上redis的,但是存储空间大.
而redis是一个一个工作在内存上的服务器数据库,它的主要工作是将用户经常访问的数据存储,因此它的传输效率是比mysql快的.但是存储空间比较小.
"""
50、遇到bug如何处理
"""
遇到bug 先查看bug是什么类型的错误,再根据错误的提示语句,定位到对应的地方
可以先尝试在错误的前后来个print 打印,看看是哪一部分错误了.
如果还没找到,就可以使用pycharm中的debug功能,加断点,一步步执行看数据变化和预想的是不是不一样!!!
"""
"""
1、细节上的错误,通过print()打印,能执行到print()说明一般上面的代码没有问题,分段检测程序是否有问题,如果是js的话可以alert或console.log
2、如果涉及一些第三方框架,会去查官方文档或者一些技术博客。
3、对于bug的管理与归类总结,一般测试将测试出的bug用teambin等bug管理工具进行记录,然后我们会一条一条进行修改,修改的过程也是理解业务逻辑和提高自己编程逻辑缜密性的方法,我也都会收藏做一些笔记记录。
4、导包问题、城市定位多音字造成的显示错误问题
"""
51、正则匹配,匹配日期2018-03-20
import re
log = "this bug is repay error.repayed 100yen. time is 2018-03-20 16:40:40 Thursday"
url='https://sycm.taobao.com/bda/tradinganaly/overview/get_summary.json?dateRange=2018-03-20%7C2018-03-20&dateType=recent1&device=1&token=ff25b109b&_=1521595613462'
reg = r"\d{4}-\d{2}-\d{2}"
print(re.findall(reg,log))
print(re.search(reg,url).group())
52、list=[2,3,5,4,9,6],从小到大排序,不许用sort,输出[2,3,4,5,6,9]
用递归实现
l1 = [2, 3, 5, 4, 9, 6]
new_l = []
def get_new_list(l):
if len(l) == 0:
return "你已更改成功"
l2 = min(l)
new_l.append(l2)
l.remove(l2)
get_new_list(l)
get_new_list(l1)
print(new_l)
lis_1 = [3, 7, 8, 9, 12, 100, 400, 540, 30, 4, 2, 1, 2, 9, 12]
lis_2 = [5, 6, 10, 13, 25, 30, 350, 340, 200, 130, 7, 8, 6, 5]
li1 = list(set(lis_1+lis_2)) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 130, 12, 13, 400, 25, 540, 30, 200, 340, 350, 100]
new_l = []
def get_new_list(l):
if len(l) == 0:
return "你已更改成功"
l2 = min(l)
new_l.append(l2)
l.remove(l2)
get_new_list(l)
get_new_list(li1)
print(new_l)
53、写一个单例模式
"""
单例模式
"""
class Mysql:
"""
实现单例模式一: 将实例化的结果保存下来
"""
__instance = None
def __init__(self, ip, port):
self.ip = ip
self.port = port
@classmethod
def dan_li(cls, ip, port):
# 判断对象是否已经实例,有就直接返回对象,没有就实例化一个对象再返回
if cls.__instance is None:
cls.__instance = cls(ip, port)
return cls.__instance
obj1 = Mysql.dan_li("127.0.0.1", 8080)
obj2 = Mysql.dan_li("127.0.0.1", 8080)
obj3 = Mysql.dan_li("127.0.0.1", 8080)
print(obj1)
print(obj2)
print(obj3)
obj4 = Mysql("127.7.7.1", 8282)
print(obj4)
class Singleton:
"""
实现单例模式2: 使用内置__new__()方法
"""
__instance = None
def __new__(cls, name, age):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
a = Singleton("jkey", 19)
b = Singleton("liu", 21)
print(a)
print(b)
a.age = 20
print(b.age) # 20,因为使用的是同一个内存地址,所以该了其中一个就相当于改了俩的age值
54、保留两位小数
题目本身只有a="%.03f"%1.3335,让计算a的结果,为了扩充保留小数的思路,提供round方法(数值,保留位数)
import re
a="%.03f"%1.3335
print(round(float(a),2))
reg = r'[0-9]\.[0-9]{2}'
print(float("".join(re.findall(reg, a))))
print(type(float("".join(re.findall(reg, a)))))
55 下面打印结果
def fn(k, v, dic={}):
dic[k] = v
print(dic)
fn("k1", 1) # {"k1":1}
fn("k2", 2) # {"k1":1,"k2":2}
fn("k3", 3, {}) # {"k3":3}
56、列出常见的状态码和意义
"""
返回响应状态码为404,表示请求资源不存在.
1xx: 信息 -- 表示服务器收到请求,需要请求者继续执行操作.
2xx: 成功 -- 操作被服务器成功接收并处理
200 ok 表明该请求被成功的完成,所请求的资源发送回客户端.
3xx: 重定向.-- 需要进一步的操作以完成请求.
如: 当你在访问一个需要登录之后才能看到的页面, 你回发现自动跳转到登录页面
4xx: 客户端请求错误, 请求包含语法错误或无法完成请求
404: -- 请求资源不存在 服务器无法根据客户端的请求找到对应的网页资源
403: -- 服务器理解请求客户端的请求, 但是拒绝执行此请求.
如:当前请求不合法或者不符合访问资源的条件.
如: 这是千万级别的俱乐部, 只有999万的你被限制无法进入
5xx: -- 服务器内部问题
500: 服务器内部错误, 无法完成请求
补充: 上述的状态码是HTTP协议规定的,其实到了公司之后每个公司还会自己定制自己的状态即提示信息
"""
"""
200 OK 请求正常处理完毕
204 No Content 请求成功处理,没有实体的主体返回
206 Partial Content get范围请求已成功处理
301 Moved Permanently 永久重定向,资源已永久分配新URL
302 Found 临时重定向, 资源已临时分配新URL
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 server Unavailable 服务器超负载或停机维护
"""
57、分别从前端、后端、数据库阐述web项目的性能优化
"""
前端:
- 对于input和用户交互的数据,可以先在用户输入的时候,就判断是否输入正确.不用将数据传到后端再开始判断
尽量减少判断中间的客户端和服务端之间跑的次数,io次数降下来.
- 对于图片可以放到精灵图中,拿取后再放大,减少http的请求次数.
- 将js压缩成一行,将空格去除减少字符数量.
- html和css放在页面的上面,JavaScript放在页面的下面,因为js中操作dom得先让文档产生,也就是网页的内容.js加载要比html和css慢,所以要优先加载html和css,以防页面显示不当给用户带来不好体验.
后端:
- 尽量不要产生死循环
- 减少io次数
- 能开多协程就不开多线程,能开多线程就不开多进程. (业务可以的话)
- 缓存存储读取次数高,变化少的数据.应用程序一般先从缓存中读取,如果读取不到或数据已失效,再访问磁盘数据库.并将数据写入缓存.
- 比如:网站首页的信息.商品的信息等.
- 异步方式: 如果有耗时操作,可以采用异步.比如:celery
数据库:
- 将经常使用的数据放入redis中,
- 数据库设计好索引,外键
- 尽量少加锁,或者使用乐观锁
- 数据库中的数据不要做运算操作
- 数据库能少干活尽量少干活
"""
58、使用pop和del删除字典中的"name"字段,dic={"name":"zs","age":18}
dic = {
"name": "jkey",
"age": 18
}
dic.pop('name')
del dic["name"]
print(dic)
59、列出常见MYSQL数据存储引擎
-- mysql 中常见的存储引擎有 myisam.innodb,memory,block_hold
-- myisam: 是mysql5.5 版本之前默认使用的存储引擎,
-- 优点: 访问速度比innodb更快
-- 缺点: 不支持事务.不支持外键,对事务完整性没有要求,数据的安全性没有innodb高.
-- 每个myisam在磁盘上存储成三个文件,其中文件名和表名都相同.但是拓展名分别为
-- MYD 存储数据
-- .frm 存储表结构
-- MYI 存储索引
-- innodb: 是mysql5.5之后默认使用的存储引擎
-- 优点: 支持事务,行级锁和外键,对数据的安全性较高
-- 缺点: 访问速度比myisam慢,但是我们更注重数据的完全
-- 每个innodb在磁盘上存储成俩个文件,其中文件名和表名都相同,但是拓展名分别为.
-- idb 存储数据 + 存储索引
-- .frm 存储结构
-- memory: 内存使用的存储引擎
-- 优点: 采用内存存储.访问速度可以得到更快的响应.
-- 缺点: 断电数据丢失,或者当mysqld守护进程崩溃时,所有的memory数据也就消失.
-- 每个memory在磁盘上存储成1个文件拓展名为
-- .frm(只有存储结构)
-- block_hole: 黑洞, 用来回收垃圾数据的,放进去就没了
-- 每个blockhole在磁盘上存储成1个文件拓展名为
-- .frm(存储结构)
60、计算代码运行结果,zip函数历史文章已经说了,得出[("a",1),("b",2),("c",3),("d",4),("e",5)]
a = zip(("a", "b", "c", "d", "e"), (1, 2, 3, 4, 5))
# a = [("a",1),("b",2)...,("e",5)]
a0 = dict(a) # a0 = {"a":1,"b":2...,"e":5}
a1 = range(10)
a2 = [i for i in a1 if i in a0] # a0 的 key为字符串,i为0-9当然不在 []
a3 = [a0[s] for s in a0]
print("a0", a0) # a0 {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
print(list(zip(("a", "b", "c", "d", "e"), (1, 2, 3, 4, 5)))) # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
print(a2) # []
print(a3) # list(a0.values()) [1,2,3,4,5]
dict()创建字典新方法
"""
dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
d = {}
for k, v in iterable:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
"""
# dict(iterable) 方法
# 通过列表套元组
dic = dict([("k1", 2), ("k2", 3)])
print(dic)
# 列表套列表
dic2 = dict([["k3", 4], ["k4", 5]])
print(dic2)
# dict(**kwargs)方法
dic3 = dict(xxx=1, yyy=2)
print(dic3)
61、简述同源策略
推荐博客: http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
"""
同源策略是指: 浏览器要求 协议相同+port端口相同+host相同
例如: 我的url是`http://www.baidu.com/index.html`
下面的url和该url是不是同源
-- `http://www.baidu.com/login.html` 同源,http协议,80端口.域名相同
-- `https://www.baidu.com/index.html` 不同源,协议不同
-- `http://www.baidu.cn/index.html` 不同源, 域名不同host就不同
-- `http://www.baidu.com:81/index.html 不同源,端口不一样,80和81
"""
"""
同源策略是为了让不同的网页中的cookie不共享,如果cookie共享的话,会导致网页中的信息外泄.
"""
62、简述cookie和session的区别
"""
1. 由于http协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识别具体的用户,而这个机制就是Session.session是保存在服务端的,有一个唯一标识.
2. 在服务端保存session的方法很多,内存,数据库,文件都有.
3. 而服务端想要识别特定的用户,就需要我们的cookie了.每次http请求来的时候,客户端都会发送相应的cookie信息到服务端.
4. 第一次创建session的时候,服务端会在http协议中告诉客户端,需要在cookie里面记录一个session id.以后每次请求把这个会话id发送到服务器,我就知道你是谁.
ps: 当客户端浏览器将cookie关闭的时候,服务端怎么实现session来跟踪呢?
-- 这个情况下,会使用一种url重写的技术来进行会话跟踪,即每次http交互,url后面都会被这样的`sid =xxxxx` 这样的参数.服务端以此来识别用户.
5. cookie其实还可以用在一些方便用户的场景,比如我们在登录某一个网站的时候,在登录点击之后,浏览器会提示你要不要保存用户密码等信息,这个就是通过cookie来实现的.
- 在下次访问网站的时候,网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了.能够方便用户.这也是cookie-小甜心饼干的由来!
"""
"""
总结:
1. session 是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群,数据库,内存,文件中.
2. cookie是客户端保存用户信息的一种机制,用来记录的一些信息,也是实现session的一种方式.
"""
"""
区别:
区别
1.存放位置:
session保存在服务器,cookie保存在客户端
2.存放的形式:
session是以对象的形式保存在服务器,cookie以字符串的形式保存在客户端
3.用途:
session适合做客户的身份验证,cookie适合保存用户的个人设置,爱好等
4.路径:
session不能区分路径,同一用户在访问一个网站期间,所有的session在任何一个地方都可以访问到;cookie中如果设置了参数路径,那么同一个网站下的cookie互相访问不到
5.安全性:
cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,session较cookie更安全一些
6.大小及数量限制:
单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。不同浏览器所含cookie的最大个数不同,一般30到50个;一般认为session没有大小限制
联系:
session需要借助cookie才能正常工作,如果客户端完全禁止cookie,session将失效,因为session是由应用服务器维持的一个服务端的存储空间,用户在连接服务器时,会由服务器生成唯一的sesssionid,用该sessionid为标识来存取服务端的session空间。而sessionid存储在cookie中,用户提交页面时会将这个sessionid提交到服务端,来存取session数据.这一过程是不用开发人员干预的,所以一旦客户端禁用cookie,那么session就得从url中获取,url会有一个类似于"sid=xxx"的参数放在url供服务器接收.
另外:
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE
sessionid是服务器和客户端链接时候随机分配的
"""
-
简述多线程、多进程
"""
1.进程
进程是操作系统中的一种资源单位
优点: 进程间的资源是相互隔离的.数据是安全的.稳定性好,一个进程出错了不会影响到别的进程.
缺点: 相对于线程,进程在开启的开销很大,并且资源不共享.
2. 线程
线程是操作系统真正干活的,是cpu的执行单位.没个进程都有一个主线程.
优点: 线程的开销相对于进程小,开启的速度也更快.并且同一个进程中的线程和线程之间资源是共享的
缺点: 线程资源不隔离.各个线程之间的资源可以相互使用,数据可能不安全.并且其中只要有一个线程出错了,就会导致进程崩溃.
应用场景:
一般多进程是使用在计算密集型的程序中
而线程是使用在io密集型的程序上.
"""
64、简述any()和all()方法
"""
any() 方法是一个判断可迭代对象中的元素真假情况,如果有正只要有任何一个,都返回True,其他的返回False
但是当这个可迭代对象是一个空的可迭代对象,则返回True.
all() 方法是一个判断可迭代对象中的元素正假情况,当一个元素中的所有元素都为真,就返回True,只要有一个假就返回False.
但是当这个可迭代对象是一个空的可迭代对象,则返回False.
"""
python中什么元素为假?
"""
为空(空字符串,空列表,空字典,空元组,空集合),None,0,False.
"""
测试all()和any()方法
a = [1, 24, 4, None, 42]
b = []
c = [0,0,0,0,1]
print(any(a)) # True
print(all(a)) # False
print(any(b)) # False
print(all(b)) # True
print(all(c)) # False
print(any(c)) # True
65、IOError、AttributeError、ImportError、IndentationError、IndexError、KeyError、SyntaxError、NameError分别代表什么异常
"""
IOError: 为IO操作异常,一般为文件操作异常
AttributeError: 为属性异常,一般为没有该属性
ImportError: 为导入异常,一般为没有这个模块
IndentationError: 缩进异常,一般为代码层级不当.
IndexError: 为索引异常, 一般是超出索引范围.
KeyError: 字典的key异常,一般为字典的key不存在
SyntaxError: 语法错误
NameError: 名称异常,一般为变量未定义.
"""
66、python中copy和deepcopy区别
"""
copy是一个浅copy,copy过来的值和原对象的子对象的值是同一个,改一个都会影响俩个对象的值.
而 deepcopy 是一个深copy,它不仅copy原对象的值,而且会独开一个内存空间存放自己对于的值,当改这个deepcopy过来的值是不会影响到原对象的值的.
"""
67、列出几种魔法方法并简要介绍用途
"""
__str__();
-- 当使用print 打印对象时,自动触发
__del__();
-- 当使用del 对对象进行删除时,自动触发.
__init__()
- 对象初始化时,自动触发
__new__()
- 创建对象时,自动触发,一般用于单例
-- 为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
__enter__()
- 出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
__exit__()
- with中代码块执行完毕时执行
"""
68、C:\Users\ry-wu.junya\Desktop>python 1.py 22 33命令行启动程序并传参,print(sys.argv)会输出什么数据?
"""
会将python 后面的参数放入一个列表中,并且改列表的元素以参数的空格分开
["1.py", "22", "33"]
"""
69、请将[i for i in range(3)]改成生成器
def func(i=0):
while i < 3:
yield i
i += 1
obj = func()
print(next(obj))
print(next(obj))
print(next(obj))
print((i for i in range(3)))
70、****a = " hehheh ",去除收尾空格
a = " hehheh "
print(a.rstrip())
71、举例sort和sorted对列表排序,list=[0,-1,3,-10,5,9]
list1 = [0, -1, 3, -10, 5, 9]
list1.sort(reverse=False) # 升序
print(list1)
print(list(sorted(list1, key=lambda k: k, reverse=True))) # 降序
72、对list排序foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4],使用lambda函数从小到大排序 [0,2,4,8,8,9,-2,-4,-4,-5,-20],正数从小到大,负数从大到小
foo = [-5, 8, 0, 4, 9, -4, -20, -2, 8, 2, -4]
print(sorted(foo, key=lambda x: (x < 0, abs(x))))
74、列表嵌套字典的排序,分别根据年龄和姓名排序
foo = [{"name": "zs", "age": 19}, {"name": "ll", "age": 54},
{"name": "wa", "age": 17}, {"name": "df", "age": 23}]
foo = [{"name": "zs", "age": 19}, {"name": "ll", "age": 54},
{"name": "wa", "age": 17}, {"name": "df", "age": 23}]
print(sorted(foo, key=lambda x: x["name"]))
print(sorted(foo, key=lambda x: x["age"]))
75、列表嵌套元组,分别按字母和数字排序
info = [
("jkey",18),
("liu",38),
("song",22)
]
print(sorted(info,key=lambda k:k[0]))
print(sorted(info,key=lambda k:k[1]))
76、列表嵌套列表排序,年龄数字相同怎么办?
info_list = [
['jkey',18],
["liu",18],
["song",22]
]
print(sorted(info_list,key=lambda k:(k[1],k[0])))
77、根据键对字典排序(方法一,zip函数)
user_info = {
"name": "jkey",
"sex": "male",
"age": "18"
}
# 方法1 使用 zip方法
f = (zip(user_info.keys(), user_info.values()))
user_items = [i for i in f]
user_item = sorted(user_items, key=lambda k: k[0])
new_dic = {item[0]: item[1] for item in user_item}
print(new_dic)
# 方法2 正常
c = sorted(user_info.items(), key=lambda x: x[0])
n_d = {i[0]: i[1] for i in c}
print(n_d)
79、列表推导式、字典推导式、生成器
"""
列表推导式
字典推导式
生成式
"""
# 列表推导式
print([i for i in range(10)]) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 字典生成式
print({f"k{i}": i for i in range(10)}) # {'k0': 0, 'k1': 1, 'k2': 2, 'k3': 3, 'k4': 4, 'k5': 5, 'k6': 6, 'k7': 7, 'k8': 8, 'k9': 9}
# 生成式
print(i for i in range(10)) # <generator object <genexpr> at 0x000002697AEA40C8>
80、最后出一道检验题目,根据字符串长度排序,看排序是否灵活运用
s_l = ["13","2412","412412","1","423","2412422"]
print(sorted(s_l,key=lambda k: len(k)))
81、举例说明SQL注入和解决办法
"""
sql注入是一种用户和数据库之间的交互出现的bug.
当用户输入的字符中有sql语句中的特殊语义的,那么会破坏掉sql语句的原本意义.
从而可以做到sql注入问题
"""
# 如
import pymysql
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='jzd123',
db='db666',
charset='utf8'
)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
user = input('username>>: ').strip()
pwd = input('pwd>>>: ').strip()
sql = "select * from user1 where username='%s' and password='%s'" % (user, pwd)
print(sql)
rows = cursor.execute(sql)
cursor.fetchall()
if rows:
print('登录成功')
else:
print("登录失败")
# 解决方案为: 将sql语句不要自己拼接,可以放入execute()方法中
rows = cursor.execute("select * from user1 where username=%s and password=%s", args=(user,pwd))
82、s="info:xiaoZhang 33 shandong",用正则切分字符串输出['info', 'xiaoZhang', '33', 'shandong']
s="info:xiaoZhang 33 shandong"
# 输出 ['info', 'xiaoZhang', '33', 'shandong']
s1 = " ".join(s.split(":"))
print(s1.split(" "))
import re
reg = "(.*):(.* )(.* )(.*)"
print(re.findall(reg, s))
print(re.split(r":| ", s))
** 83、正则匹配以163.com结尾的邮箱 **
import re
s = """
www.fadaf@163.com
www.fadaf@qq163xx.com
www.fadaf@wx163x.com
www.fadaf@wb163.com
"""
reg = r'(.*?@*163\.com$)'
s = s.strip().split("\n")
for i in s:
res = re.findall(reg, i)
if res:
print(res)
84、递归求和
递归完成1-n的和
# 递归完成1-n的和
def my_sum(x):
if x > 0:
res = x + my_sum(x - 1)
else:
res = 0
return res
print(my_sum(10))
85、python字典和json字符串相互转化方法
import json
# 序列化
dic = {"name":"jkey"}
json.dump(dic,open("a.json","w"))
# 反序列化
dic2 = json.load(open("a.json","r"))
print(dic2)
86、MyISAM 与 InnoDB 区别:
"""
MyISAM: 是mysql5.5版本之前默认使用的存储引擎
优点: 可以很快的根据索引查询
缺点: 不支持事务,外键和行级锁.
每个MyISAM存放在磁盘中有三个表:
-- myi存储结构
-- myd存储数据
-- myl存储索引
innodb: 是mysql5.5版本之后的默认使用的存储引擎
优点: 支持行级锁,事务,外键.
缺点: 相对于MyISAM查询会慢一点点
每个innoDB存放在磁盘上有俩个表:
-- idb 存储数据和存储索引
-- ifm 存储表结构
"""
87、统计字符串中某字符出现次数
import collections
s = "fqwfaffsfaf哈哈fecxvweagk"
print(collections.Counter(s)) # 所有的字符出现的次数
print(s.count("哈")) # 哈字符出现的次数
88、字符串转化大小写
s = 'hello'
print(s.upper())
print(s.lower())
89、用两种方法去空格
s = ' wwwaf saf '
print("".join(i for i in s if i!=" "))
print(s.strip().replace(" ",""))
90、正则匹配不是以4和7结尾的手机号 (正常手机号)
import re
phone_list = ["13870722587", "10086", "13870722582", "110"]
reg = "1[0-9]{9}[^47]$"
for i in phone_list:
res = re.findall(reg, i)
if res:
print(res)
91、简述python引用计数机制
"""
python 中有一个名叫垃圾回收机制gc,它采用的方式就是引用计数,分代回收,和标记清除
-- 其中的引用计数指的是名称对应的值之间的绑定过程中引用了计数,当绑定成功一个名称空间就让该对应的值的计数+1
-- 分代回收,指的是将定期回收计数为0的内存地址,而一些常用的内存地址就可以将其回收的周期延长,将一些不常用的内存地址,就可以将其周期简短,内存地址空间小的周期也可以延长
-- 标记清除指的是,当名称没有被调用,也就是后续没有使用了,就会将计数-1,一直到计数为0,就会清除标记,并回收资源.
"""
92、int("1.4"),int(1.4)输出结果?
# int("1.4")报错,int(1.4)输出1
93、列举3条以上PEP8编码规范
"""
-- 每段代码之间的缩进以4个空格为一级.
-- 定义变量名为一个英文单词,采用"_"拼接的方式
-- 当变量赋值的时候的"=" 俩边要有空格.
-- 行内最大字数不要成功120个字符
-- 俩个函数之间的定义,为俩行距离.
-- 类定义为驼峰体
-- 三引号进行注释
"""
94、正则表达式匹配第一个URL
import re
s = '<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js">' \
'</script><script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>'
reg = r'src="(.*?)"'
print(re.search(reg, s).group(1))
95、正则匹配中文
import re
s = "你好,您是谁.hahah"
reg = r"[\u4e00-\u9fa5]+" # \u4e00-u9fa5代表的是中文字符
print(re.findall(reg,s))
96、简述乐观锁和悲观锁
"""
1.悲观锁
-- 悲观锁指的是一种锁使用的方式,它是悲观的,它会将所有的用户当作它要修改的数据的竞争对象,会在拿到数据的时候,就先加锁,先保证数据的安全性,这就会导致并发效果不好,或者说吞吐量低.
2. 乐观锁
-- 乐观锁指的也是一种锁使用的方式,是一种加锁的思想,并不真正存在
-- 它是很乐观的,它默认不会将拿到的数据直接加锁,而是会在提交的时候,拿着当前的版本号于现在数据库中对应的版本号进行对比,落是不一样就返回结果给用户处理,就导致事务有一些提交失败的情况.
-- 虽然加大了事务提交的失败率,但是提高了并发量,就加大了吞吐量.
-- 多适用于读的情况
"""
97、r、r+、rb、rb+文件打开模式区别
"""
r 表示的是rt 文本可读模式 以字符串的类型进行读取
r+ 表示的是rt+ 文本可读并且也可以写 以字符串的类型进行读取
rb 表示的是bytes可读模式 以二进制的类型进行读取
rb+ 表示的是bytes可读可写模式 以二进制的类型进行读取
-----以上在打开文件时,指针在文件的开头
"""
98、Linux命令重定向 > 和 >>
"""
Linux允许将命令执行 结果 重定向到一个 文件
将本应显示在终端上的内容 输出/追加 到指定的文件中
而 > 表示的是直接写入文件,类似于python文件对象中的w,会将原文件内容覆盖.
>> 表示的是追加写入文件,类似于python文件对象中的a,默认会在文件的末尾追加内容.
"""
# 例如:
echo hello python > 1.txt # 将打印结果hello python 写入到1.txt文件中
echo hello python >> 1.txt # 将打印结果 hello python 追加写入到1.txt中
**99、正则表达式匹配出<html><h1>www.itcast.cn</h1></html>
import re
s = "fafafa<html><h1>www.itcast<pre>faf></pre>.cn</h1></html>fafasfaf"
reg = r"<.*>"
print(re.search(reg, s).group())
100、python传参数是传值还是传址?
"""
传值就是把一个参数的值给这个函数,其中的更改不会影响原来的值。
传址:即传引用,直接把这个参数的内存地址传递进去,直接去这个内存地址上进行修改。
Python中的传参都是传递对象的引用。
但是可以这样理解:
-- 不可变数据类型,传的是内存地址也相对于是值
-- 可变数据类型,那么传的就是内存地址
"""
str1 = 'hello'
def func(str1):
str1 += "python"
func(str1)
print(str1) # hello
l = ["hello"]
def func1(l):
l.append('python')
l.remove("hello")
func1(l)
print(l) # ['python']
101、求两个列表的交集、差集、并集
l1 = [1,424,24,5,6,63,43,55]
l2 = [1,15,42,52,43,45,124]
# 并集
l3 = list(set(l1+l2))
print(l3)
# 差集
l4 = [i for i in l1 if i not in l2] # l1 - l2
print(l4)
l5 = [j for j in l2 if j not in l1] # l2 - l1
print(l5)
# 交集
l6 = [i for i in l2 if i in l1]
print(l6)
102、生成0-100的随机数
import random
print(100 * random.random())
print(random.randint(0,100))
103、lambda匿名函数好处
"""
lambda 为匿名函数,好处就是可以搭配着内置的函数方法一起使用,可以起到代码精简的效果
- 如:
print(list(map(lambda k:k*k,[1,2,3,4])))
"""
104、常见的网络传输协议
"""
HTTP
HTTPS
FTP
UDP
FTP
SMTP
"""
105、单引号、双引号、三引号用法
"""
单引号和双引号没什么区别,但是需要注意的是当作字符串值的时候,引号嵌套问题,不能外面用了单/双引号,里面也用一样的引号,就会出现配对不符合原意的效果
三引号一般是用来注释的,对文件的大概内容进行注释..
"""
106、python垃圾回收机制
"""
python垃圾回收机制简称gc
-- 有三大技术
-- 计数引用
-- 一个名称和一个内存地址直接绑定后,就会在上面有一个计数,绑定一个+1
-- 分代回收
-- 将经常使用的名称和内存地址的等级设置高一点,回收的周期也就长一点
-- 将内存地址小的,等级也可以设置高一点
-- 但对应内存地址占用资源大,且不经常使用的名称内存地址等级设置低一点,回收的周期可以快一点
-- 标记清除
-- 当名称没有被引用时,名称和内存地址直接的计数-1,直到内存地址没有任何一个名称与之对应,即计数为0时,就可以将标记清除回收了
"""
107、HTTP请求中get和post区别
"""
get: 为请求
-- 即一般为请求服务端返回数据
-- 请求的数据一般以key:value的形式放到url中发送给服务端
post: 为提交
-- 将客户端输入的信息提交给服务端
-- 提交的数据一般以key:value的形式放到一个数据包中,隐藏起来,对数据进行了保护作用
"""
108、python中读取Excel文件的方法
"""
可以通过pandas模块中的read_excel方法 读取execl文件中的内容
注意要安装: pip install pandas/xlrd/openpyxl
"""
# 如
import pandas as pd
res = pd.read_excel(r"1.xlsx")
print(res)
109、简述多线程、多进程
"""
进程:
1、操作系统进行资源分配和调度的基本单位,多个进程之间相互独立
2、稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制
线程:
1、CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程的所有资源
2、如果IO操作密集,则可以多线程运行效率高,缺点是如果一个线程崩溃,都会造成进程的崩溃
应用:
IO密集的用多线程,在用户输入,sleep 时候,可以切换到其他线程执行,减少等待的时间
CPU密集的用多进程,因为假如IO操作少,用多线程的话,因为线程共享一个全局解释器锁,当前运行的线程会霸占GIL,其他线程没有GIL,就不能充分利用多核CPU的优势
"""
110、python正则中search和match
"""
searsh 表示的是全部匹配,返回的是匹配的第一个字符
match 和search一样,但是它要求一定要什么什么字符开头,相对于search中的正则表达式前面加上^.
"""
"""
官方一点:
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
re.search 扫描整个字符串并返回第一个成功的匹配。
"""