Python面试题汇总

转自https://yq.aliyun.com/articles/665799?spm=a2c6h.12873639.0.0.597310c4kplhVc

1. 如何在一个函数内部修改全局变量

利用global 修改全局变量

a = 5
def gn():
    global a
    a = 8
print('1:', a)
gn()
print('2:', a)
#1: 5
#2: 8

2、谈下python的GIL

GIL 是python的全局解释器锁,同一进程中假如有多个线程运行,一个线程在运行python程序的时候会霸占python解释器(加了一把锁即GIL),使该进程内的其他线程无法运行,等该线程运行完后其他线程才能运行。如果线程运行过程中遇到耗时操作,则解释器锁解开,使其他线程运行。所以在多线程中,线程的运行仍是有先后顺序的,并不是同时进行。

多进程中因为每个进程都能被系统分配资源,相当于每个进程有了一个python解释器,所以多进程可以实现多个进程的同时运行,缺点是进程系统资源开销大

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

打开文件在进行读写的时候可能会出现一些异常状况,如果按照常规的f.open

写法,我们需要try,except,finally,做异常判断,并且文件最终不管遇到什么情况,都要执行finally f.close()关闭文件,with方法帮我们实现了finally中f.close

with open("./1.txt","wb") as f

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

r , 表示需要原始字符串,不转义特殊字符 r"\abc" == "\\abc"

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

import re
str = '<div class="nam">中国</div>'
res = re.findall(r'<div class=".*?">(.*?)</div>', str)
print(res[0])
#中国

 6、python中断言方法举例

assert()方法,断言成功,则程序继续执行,断言失败,则程序报错

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

distinct对其后面的全部列都有效,也就是只有全部列都重复才会去除,其中只要有一列不重复都不会去除

select distinct name from student

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

不可变数据类型:数值型、字符串型string和元组tuple

不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象(一个地址),如下图用id()方法可以打印对象的id

a=3
b=3
id(a)
140706537321360
id(b)
140706537321360

可变数据类型:列表list和字典dict;

允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。

a=[1,2]
b=[1,2]
id(a)
2197759542216
id(b)
2197760532232

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

sum = lambda a,b:a*b
print(sum(4,5))
#20

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

dict={"name":"zs","age":18,"city":"深圳","tel":"1362626627"}
# items将dic返回为二元数组,i[0]表示第一项
LIST = sorted(dict.items(),key=lambda i:i[0], reverse=False)
print(list(LIST))
new_d = {}
for i in LIST:
    new_d[i[0]]=i[1]
print(new_d)
#[('age', 18), ('city', '深圳'), ('name', 'zs'), ('tel', '1362626627')]
#{'age': 18, 'city': '深圳', 'name': 'zs', 'tel': '1362626627'}

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

from collections import Counter
s = "kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h"
res = Counter(s)
print(res)
print(res["j"]) #结果类似字典
#Counter({'l': 9, ';': 6, 'h': 6, 'f': 5, 'a': 4, 'j': 3, 'd': 3, 's': 2, 'k': 1, 'g': 1, 'b': 1})
#3

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

*

匹配前一个字符0或无限次  ab*c == ac,abc,abbc,….

+

匹配前一个字符1或无限次  ab*c == abc,abbc,….【少了ac】

匹配前一个字符0或一次  ab?c == ac,abc

{m}

匹配前一个字符m次  ab{3}c == abbbc

{m, n}

匹配前一个字符m<->n次  ab{1,3}c == abc,abbc,abbbc

import re
a = "not 404 50.56 found 张三 99 深圳"
LIST = a.split(" ")
res = re.findall('\d+\.?\d*|[a-zA-Z]+', a)
for i in res:
    if i in LIST:
        LIST.remove(i)
STR = "".join(LIST)
print(STR)
#张三深圳

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

a = list(range(10))
def func(n):
    return n%2==1
newList = filter(func, a) #<filter object at 0x000002C3AA293358>
rst = [i for i in newList]
print(rst)
# [1, 3, 5, 7, 9]

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

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

15、两个列表[1,5,7,9]和[2,2,6,8]合并为[1,2,2,3,6,7,8,9]

extend可以将另一个集合中的元素逐一添加到列表中,区别于append整体添加

[1,5,7,9].extend([2,2,6,8])

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

python:os.remove(文件名)

linux: rm 文件名

17、log日志中,我们需要用时间戳记录error,warning等的发生时间,请用datetime模块打印当前时间戳 

import datetime
a = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+'星期: '+str(datetime.datetime.now().isoweekday()))
print(a)
#2020-06-07 10:56:46星期: 7

18、数据库优化查询方法

外键、索引、联合查询选择特定字段等等

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

 自定义异常用raise抛出异常

def fn():
    try:
        for i in range(5):
            if i > 2:
                raise Exception("num lager than 2")
    except Exception as ret:
        print(ret)
fn()
#num lager than 2

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

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

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

import re
s = "<a>hh</a><a>gg</a>"
rst1 = re.findall("<a>(.*)</a>", s)
print(rst1)
rst2 = re.findall("<a>(.*?)</a>", s)
print(rst2)
#['hh</a><a>gg']
#['hh', 'gg']

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

join()括号里面的是可迭代对象,x插入可迭代对象中间,形成字符串,结果一致

a='abc'
b='def'
c=['d','e','f']
print(a.join(b))
print(a.join(c))
#dabceabcf
#dabceabcf

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

try..except..else没有捕获到异常,执行else语句

try..except..finally不管是否捕获到异常,都执行finally语句

23、python中交换两个数值

a,b=b,a

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

import re
STR = "zhangsan 98fen"
ret = re.sub(r"\d+","100",STR)
print(ret)
#zhangsan 100fen

25、写5条常用sql语句

show databases;

show tables;

desc 表名;

select * from 表名;

delete from 表名 where id=5;

update students set gender=0,hometown="北京" where id=5

26、遇到bug如何处理

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

2、如果涉及一些第三方框架,会去查官方文档或者一些技术博客。

3、对于bug的管理与归类总结,一般测试将测试出的bug用teambin等bug管理工具进行记录,然后我们会一条一条进行修改,修改的过程也是理解业务逻辑和提高自己编程逻辑缜密性的方法,我也都会收藏做一些笔记记录。

4、导包问题、城市定位多音字造成的显示错误问题

27、保留两位小数

round(float(a),2)

28、数据库优化:

1、如有条件,数据可以存放于redis,读取速度快

2、建立索引、外键等

29、列出常见MYSQL数据存储引擎

InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。

MyISAM:插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比 较低,也可以使用。

MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。

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

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

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

python中什么元素为假?

答案:(0,空字符串,空列表、空字典、空元组、None, False)

bool({})
False
bool([])
False
any(["1",""])
True
all(['1',''])
False

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

IOError:输入输出异常

AttributeError:试图访问一个对象没有的属性

ImportError:无法引入模块或包,基本是路径问题

IndentationError:语法错误,代码没有正确的对齐

IndexError:下标索引超出序列边界

KeyError:试图访问你字典里不存在的键

SyntaxError:Python代码逻辑语法出错,不能执行

NameError:使用一个还未赋予对象的变量

32、python中copy和deepcopy区别

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

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

浅拷贝copy有两种情况:

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

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

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

33. sort和sorted对列表排序

sort在原列表上操作,无返回值;sorted是有返回值的。reverse=False从小到大;reverse=True从大到小

34、使用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],正数从小到大,负数从大到小(传两个条件,x<0和abs(x))第一个条件优先级更高

foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4]
# 先按正负排序,再对正数负数分别排序
a=sorted(foo,key=lambda x:(x<0,abs(x)))
print(a)
[0, 2, 4, 8, 8, 9, -2, -4, -4, -5, -20]
a=sorted(foo,key=lambda x:(x<0))
a=sorted(foo,key=lambda x:(x<0,x))
print(a)
[0, 2, 4, 8, 8, 9, -20, -5, -4, -4, -2]

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

|表示或,根据冒号或者空格切分

s="info:xiaoZhang 33 shandong"
import re
res = re.split(r":| ", s)
res
['info', 'xiaoZhang', '33', 'shandong']

36、用两种方法去空格

STR = "H E L L O"
res = STR.replace(" ", "")
print(res)

res = STR.split(" ")
print("".join(res))

37、简述python引用计数机制[垃圾回收]

python垃圾回收主要以引用计数为主,标记-清除和分代清除为辅的机制,其中标记-清除和分代回收主要是为了处理循环引用的难题。

引用计数算法

当有1个变量保存了对象的引用时,此对象的引用计数就会加1

当使用del删除变量指向的对象时,如果对象的引用计数不为1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除

736d1bb69d7b5cfe7aa1d4c810b651f35e147b65

38、正则匹配中文

import re
title = "你好,hello,世界"
pattern = re.compile(r'[\u4e00-\u9fa5]+')
result = pattern.findall(title)
res = re.findall(pattern, title)
print(result)
print(res)
['你好', '世界']
['你好', '世界']

39. 字典列表保存一个对象【很不寻常,就像C++传的是地址】

40、python传参数是传值还是传址?

Python中函数参数是引用传递(注意不是值传递)。对于不可变类型(数值型、字符串、元组),因变量不能修改,所以运算不会影响到变量自身;而对于可变类型(列表字典)来说,函数体运算可能会更改传入的参数变量。

41、求两个列表的交集、差集、并集

c51426f06f5c1f525c5871b6b8be4e059b3af8d4

42、HTTP请求中get和post区别

1、GET请求是通过URL直接请求数据,数据信息可以在URL中直接看到,比如浏览器访问;而POST请求是放在请求头中的,我们是无法直接看到的;

2、GET提交有数据大小的限制,一般是不超过1024个字节,而这种说法也不完全准确,HTTP协议并没有设定URL字节长度的上限,而是浏览器做了些处理,所以长度依据浏览器的不同有所不同;POST请求在HTTP协议中也没有做说明,一般来说是没有设置限制的,但是实际上浏览器也有默认值。总体来说,少量的数据使用GET,大量的数据使用POST。

3、GET请求因为数据参数是暴露在URL中的,所以安全性比较低,比如密码是不能暴露的,就不能使用GET请求;POST请求中,请求参数信息是放在请求头的,所以安全性较高,可以使用。在实际中,涉及到登录操作的时候,尽量使用HTTPS请求,安全性更好。

43、简述多线程、多进程

进程:

1、操作系统进行资源分配和调度的基本单位,多个进程之间相互独立

2、稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制

线程:

1、CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程的所有资源

2、如果IO操作密集,则可以多线程运行效率高,缺点是如果一个线程崩溃,都会造成进程的崩溃

应用:

IO密集的用多线程,在用户输入,sleep 时候,可以切换到其他线程执行,减少等待的时间

CPU密集的用多进程,因为假如IO操作少,用多线程的话,因为线程共享一个全局解释器锁,当前运行的线程会霸占GIL,其他线程没有GIL,就不能充分利用多核CPU的优势

44.__new____init__功能上的区别

__new____init__的主要区别在于:__new__是用来创造一个类的实例的(constructor),而__init__是用来初始化一个实例的(initializer)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值