52道Python面试题,让你在学习中,打开科技公司大门,不惧面试

python中is和==的区别

  1. Python中对象包含的三个基本要素,分别是:id(身份标识) 、type(数据类型)和value(值)。
  2. ‘==’比较的是value值
  3. ‘is’比较的是id
  4. 简述read、readline、readlines的区别
  5. read读取整个文件
  6. readline读取下一行数据
  7. readlines读取整个文件到一个迭代器以供我们遍历(读取 到一个list中,以供使用,比较方便)
  8. 举例说明创建字典的至少两种方法

# 1

dict1 = {key1:v1,key2:v2}

# 2

dict2 = {}

dict2[key1] = v1

dict2[key2] = v2

# 3

dict3 = dict(key1=v1,key2=v2)

4.*args,**kwargs的作用是什么?如何使用?

*args和**kwargs通常使用在函数定义里,*args允许函数传入不定量个数的非关键字参数,**kwargs允许函数传入不定量个数的关键字参数

5.python中match()和search()的区别?

  1. match()函数只检测RE是不是在string的开始位置匹配, search()会扫描整个string查找匹配, 也就是说match ()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none

6.一个函数接收文件夹的名称作为参数,返回该文件中所有文件的全路径,请补全缺失的代码。

def print_directry_contents(spath):

import os

files_list = os.listdir(spath)

for file in files_list:

print(os.path.realpath(file))

7.阅读下面的代码,写出A0,A1至An的最终值

A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))

A0 = {'a':1,'b':2,'c':3,'d':4,'e':5}

A1 = range(10)

A1 = [0,1,2,3,4,5,6,7,8,9]

A2 = [i for i in A1 if i in A0]

A2 = [] # 当对字典进行in判断是,判断的是key

A3 = [A0[s] for s in A0]

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

A4 = [i for i in A1 if i in A3]

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

  • 请写一段代码实现Python中list去重。

# 方法1

list1 = [1,1,2,3,3,4]

set1 = set(list1)

list1 = list(set1)

# 方法2

list2 = []

for i in list1:

if i not in list2:

list2.append(i)

  1. 创建一个装饰器将下面函数输入的字符串首字母大写。

def greetins(word='hi there'):

return word.lower()

from functools import wraps

def start_word_upper(func):

@wraps(func)

def inner(*args,**kwargs):

word = func(*args,**kwargs)

return word.capitalize()

return inner

# 装饰器可以在:

# 1.函数调用之前对函数参数进行操作,直接返回被装饰函数的返回值

10.描述yield作用。

1. 保存当前运行状态(断点),然后暂停执行,即将函数挂起

2.将yeild关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用,当使用next()、send()函数让函数从断点处继续执行,即唤醒函数。

11.装饰器。

1. 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。

2.功能:1.引入日志;2.函数执行时间统计;3.执行函数前预备处理;4.执行函数后清理功能;5.权限校验;6.缓存

12.你对多线程和多进程的理解。

1.进程是系统进行资源分配和调度的一个独立单位,线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源;

2.一个程序至少有一个进程,一个进程至少有一个线程;

3.线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高;

4.进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率 ;

5.线线程不能够独立执行,必须依存在进程中;

6.优缺点:线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。

13.线程中start方法和run方法的区别?

1.若调用start,则先执行主进程,后执行子进程;

2. 若调用run,相当于正常的函数调用,将按照程序的顺序执行

14.linux命令 grep awk sed是怎么用的?

1.grep:Global Regular Expression Print

2.

15.python是怎么进行内存管理的?

1.引用计数:python内部使用引用计数,来保持追踪内存中的对象,Python内部记录了对象有多少个引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不再需要时,这个对象的引用计数为0时,它被垃圾回收。

1.引用计数加1的情况:

1.对象被创建:x=4

2.另外的别人被创建:y=x

3.被作为参数传递给函数:foo(x)

4.作为容器对象的一个元素:a=[1,x,'33']

2.引用计数减少情况

1.一个本地引用离开了它的作用域。比如上面的foo(x)函数结束时,x指向的对象引用减1。

2.对象的别名被显式的销毁:del x ;或者del y

3.对象的一个别名被赋值给其他对象:x=789

4.对象从一个窗口对象中移除:myList.remove(x)

5.窗口对象本身被销毁:del myList,或者窗口对象本身离开了作用域

2.垃圾回收

1.当内存中有不再使用的部分时,垃圾收集器就会把他们清理掉。它会去检查那些引用计数为0的对象,然后清除其在内存的空间。当然除了引用计数为0的会被清除,还有一种情况也会被垃圾收集器清掉:当两个对象相互引用时,他们本身其他的引用已经为0了。

2.垃圾回收机制还有一个循环垃圾回收器, 确保释放循环引用对象(a引用b, b引用a, 导致其引用计数永远不为0)。

3.内存池机制:在Python中,许多时候申请的内存都是小块的内存,这些小块内存在申请后,很快又会被释放,由于这些内存的申请并不是为了创建对象,所以并没有对象一级的内存池机制。这就意味着Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。

1.Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。

2.Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的 malloc。另外Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。

16.什么是lambda函数?他有什么好处? lambda函数是匿名函数;使用lambda函数能够创建小型匿名函数。这种函数得名于省略了用def声明函数的标准步骤; 例:

f = lambda x,y:x+y # 求两个函数的和。 x,y是参数,x+y是函数返回值

17.python中tuple和list的转换

#tuple ---> list

tuple1 = (1,2,3)

list1 = list(tuple1)

# list ---> tuple

list2 = [1,2,3]

tuple2 = tuple(list2)

18.python中如何拷贝一个对象?(赋值,浅拷贝,深拷贝的区别)

答:赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。

浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变){1,完全切片方法;2,工厂函数,如list();3,copy模块的copy()函数}

深拷贝:创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变){copy模块的deep.deepcopy()函数}

19.介绍一下except的用法和作用?

try:

pass

except Exception as e:

print(e)

finally:

pass

捕获try except中间代码发生的异常,如果发生异常执行except的代码,不管是否发生异常都执行finally中的代码

except可以有0个或多个,如果有多个从上到下依次根据异常类型匹配,匹配某个Exception这执行对应的except中代码

20.用python匹配HTML tag的时候,<.*>和<.*?>有什么区别?

  1. <.*>匹配结果是:HTML tag;
  2. <.*?>匹配到的结果是:""。 ? 表示非贪婪,搜到符合的结果既返回

21.有没有一个工具可以帮助查找Python的bug和进行静态的代码分析?

1.PyChecker是一个python代码的静态分析工具,它可以帮助查找python代码的bug, 会对代码的复杂度和格式提出警告

2.Pylint是另外一个工具可以进行codingstandard检查

22.请写一段脚本,查找/data/test 目录下3天前的文件,从中挑选出大小超过10M的删除掉。

#!/bin/sh

find "/data/test" -mtime +3 -size +10M -exec rm {} \

23.请写一段python代码,替换掉目标字符串中的[北京市,技术,有限,公司]等字符,比如:目标字符串:北京市麦达技术数字有限公司,要求替换输出 麦达数字。

str1 = "北京市麦达技术数字有限公司"

str2 = str1.replace("北京市","").replace("技术","").replace("有限","").replace("公司","")

24.有一个纯字符串,编写一段代码,列出其所有字符的大小写组合

如 :字符串“ji”,字母组合['ji','jI','Ji','JI']

即每个字符的大小写组合

def word_group(word):

word = word.lower()

dict = {}

list = []

for letter in word:

if not dict:

list.append(letter)

list.append(letter.upper())

dict[word.index(letter)] = list

else:

list = []

for i in dict[word.index(letter)-1] :

list.append(i + letter)

list.append(i+ letter.upper())

dict[word.index(letter)] = list

print(dict[len(word)-1])

25.简述一下你熟悉的NOSQL,它有什么优点和缺点?

redis:

优点:

- 读写性能优异;

- 支持数据持久化,支持AOF和RDB两种持久化方式;

- 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离;

- 数据结构丰富:除了支持string类型的value外还支持string、hash、set、sortedset、list等数据结构。

缺点:

- Redis不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复;

- 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性;

- Redis的主从复制采用全量复制,复制过程中主机会fork出一个子进程对内存做一份快照,并将子进程的内存快照保存为文件发送给从机,这一过程需要确保主机有足够多的空余内存。若快照文件较大,对集群的服务能力会产生较大的影响,而且复制过程是在从机新加入集群或者从机和主机网络断开重连时都会进行,也就是网络波动都会造成主机和从机间的一次全量的数据复制,这对实际的系统运营造成了不小的麻烦;

- Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。

26.使用一个正则表达式设计一个程序,将字符串"<a href=www.baidu.com>正则表达式题库</a><a href=www.cdtest.cn></a>"的www.baidu.com和www.cdtest.cn同时匹配出来。

import re

str = "<a href=www.baidu.com>正则表达式题库</a><a href=www.cdtest.cn></a>"

regex = r"href=(.*?)>"

ret_list = re.findall(regex,str)

27.设计一个程序,求出1+3!+5!+7!+9!+50!的和。

# 求1+3!+5!+7!+9!

m = 0

for i in range(1,6):

n = 1

for j in range(1,2*i):

n = n*j

m += n

# 求50!

l = 1

for x in range(1,51):

l = l*x

# 和

sum = m+l

print(sum)

28.把字符串“HELLO PYTHON”从大写字母全部转换成小写字母并换行显示,然后输出到计算机c盘的hello.txt文件中保存。

str = 'HELLO PYTHON'

with open(r'C:/hello.txt','a') as f:

for letter in str:

letter = letter.lower()

f.write(letter)

f.write(' ')

29.设计一个小程序,采用任意数据结构方法,输入年、月、日后能判定当前日期在本年是第几天。

def judge_dayth(y=None,m=None,d=None):

# 判断是否是润年

if y%4==0 and y%100!=0 or y%400==0:

m_list = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

else:

m_list = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

if m == 1:

dayth = d

else:

m_days = 0

for i in range(m-1):

m_days += m_list[i]

dayth = m_days + d

print(dayth)

30.给定一个值为整数的数组int_array,找出int_array中第二大的整数。

说明:如果最大的整数在int_array中出现不止一次,则最大整数为第二大整数。

例:

输入:[1,2,3,4,5]

输出:4

输入:[5,5,4,4,3]

输出:5

import json

def find_max(int_array):

max_int = 0

for i in int_array:

if i > max_int:

max_int = i

return max_int

int_array = json.loads(input()) # 将字符串转化为列表

max_int = find_max(int_array)

int_array.remove(max_int)

max_int = find_max(int_array)

print(max_int)

31.使用python将字符串“1.2.3.4.5”转换为字符串“5|4|3|2|1”

str = "1.2.3.4.5"

li = str.split(".") # li = [1,2,3,4,5]

# 列表倒序

li = li[::-1] # li = list(reversed(li)) 或者 li = sorted(li,reverse=True)

# 字符串拼接

str = "|".join(li)

32.请分别描述python2.x和python3.x中import包时的路径搜索顺序

import sys

sys.path # 查看搜索路径

33.Python的正则表达式匹配时间信息。

import re

data_info = "现在的时间是:2018-3-10 11:52"

regex = r"d{4}-d{1,2}-d{1,2}sd{1,2}:d{2}"

ret = re.search(regex,data_info).group

print(ret)

34.使用python编写一个装饰器,打印被装饰函数的输入与输出。

from functools import wraps

def print_io(func):

@wraps(func)

def inner(*args,**kwargs):

print("函数的输入:{}".format(*args,**kwargs))

ret = func(*args,**kwargs)

print("函数的输出:{}".format(ret))

return ret

return inner

35.阐述range和xrange的区别,并且用Python仿写xrange函数。 Python 2.x 中:

range 函数说明:range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列。

xrange 函数说明:用法与range完全相同,所不同的是生成的不是一个数组,而是一个生成器。 python 3.x中:

已经将xrange函数删除,range函数同Python2.x 中的xrange函数用法相同

def xrange(*args,**kwargs):

for i in range(*args,**kwargs):

yield i

36.列举几种你曾经常用的python包并且解释其功能及用法

os模块:os模块包装了不同操作系统的通用接口,使用户在不同操作系统下,可以使用相同的函数接口,返回相同结构的结果。

sys模块:给命令行传参

time、re、requests...

# 我觉得这个题的根据要应聘的岗位填一些对应的模块,比方说爬虫方向就写requests,lxml,selenium...

37.合并列表a=[1,2,3,4]和b=[5,6,7,8]

a.extend(b)

38.列表a,请写出实现正序排列,倒序排列,逆序排列的内置方法。

# 正序

a.sort()

# 倒序

a.sort(reverse=Ture)

# 逆序

a.reverse()

39.字典d={"k":1,"v":2},请写出d.items()的结果。

dict_items([("k",1),("v",2)])

40.复杂列表[{"k":1,"v":2},{"k":12,"v":22},{"k":13,"v":32}],请用内置方法写出k的倒序排列的代码。

li = [{"k":1,"v":2},{"k":12,"v":22},{"k":13,"v":32}]

li.sort(key=lambda dict:dict["k"],reverse=True)

print(li)

41.集合s = set([1,2,3,4]),d = set([2,4,9,0,3]),请用内置方法写出它们的并集,交集,对称公差。

# 交集

s|d # {2, 3, 4}

# 并集

s&d # {0, 1, 2, 3, 4, 9}

# 对称差集

s^d # {0, 1, 9}

42.请随机输出一个大于0小于1的数;请随机输出一个100以内的整数。

import random

print(random.random()) # 0<1

print(random.randint(1,100)) # 100以内整数

43.长度未知的元组a=(1,3,4,5,6,...),请随机输出n项

import random

a=(1,3,4,5,6,...)

a = list(a)

for i in range(n):

b = a[random.randint(0,len(a))-1]

print(b)

a.remove(b)。

44.代码a=[{i:j} for i,j in enumerate(range(5))],请写出a的最终结果。

a = [{0:0},{1:1},{2:2},{3:3},{4:4}]

# enumerate()函数:枚举、列举,返回一个可迭代对象的索引和索引对应的值

45.分别说说cmp,map,filter的作用?

# cmp:compare比较

cmp(a,b) # a<b 返回-1 a>b 返回1 a=b返回0

# map:映射

map(function, iterable) # 将function作用于iterable,每个元素,将对应输出结果保存为一个list

# 例:

def plus_one(x):

return x+1

map(plus_one,[1,2,3,4]) ===>[2,3,4,5]

# filter:过滤器

filter(function, iterable) # 将 function依次作用于iterable的每个元素,如果返回值为true, 保留元素,否则从iterable里面删除

# 例:

def bigger_than_three(x):

return (x>3)

filter(bigger_than_three,[1,2,3,4,5]) ===>[4,5]

46.请阐述__new__和__init__的区别?

__new__:创建对象时调用,会返回当前对象的一个实例

__init__:创建完对象后调用,对当前对象的一些实例初始化,无返回值

调用顺序:先调用__new__生成一个实例再调用__init__方法对实例进行初始化,比如添加属性。

47.写一段代码实现单例模式。

class Singleton(object):

def __new__(cls):

# 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象

if not hasattr(cls, 'instance'):

cls.instance = super(Singleton, cls).__new__(cls)

return cls.instance

48.用yield写出一个生成器。

def generator():

for i in range(5):

yield i

49@classmethod、@staticmethod、@property都是啥意思?

@classmethod:类方法,类方法是给类用的,类在使用时会将类本身当做参数传给类方法的第一个参数,python为我们内置了函数classmethod来把类中的函数定义成类方法。

@staticmethod:静态方法

@property:将一个实例方法提升为属性,便于访问

50.请解释一下Gevent和threading/multiprocessing的关系。

51.请解释一下cookie和session的关系,以及csrf的攻击和防范方法。

  • cookie保存在浏览器端,session保存在服务器端,但是为了区分不同的客户端,服务器会在浏览器中发送一个对应的sessionid保存到cookies中,下次浏览器请求服务器的时候会将sessionid一并发送给服务器。所以session机制依赖于cookie机制。
  • csrf攻击:cross site request forgery 跨站请求伪造
  • 原理:
  • 1.User(C)访问信任网站Web(A),Web(A)会在User(C)处设置A的cookie;
  • 2.User(C) 在没有登录A的情况下,访问危险网站Web(B),B要求User(C)访问Web(A);
  • 3.User(C)在Web(B)的要求下,带着Web(A)的cookie访问Web(A),这样Web(B)就达到了模拟用户操作的目的
  • 防御:
  • 1.通过 referer、token 或者 验证码 来检测用户提交。
  • 2.尽量不要在页面的链接中暴露用户隐私信息。
  • 3.对于用户修改删除等操作最好都使用post 操作 。
  • 4.避免全站通用的cookie,严格设置cookie的域。

52.描述对super,pass,yield,lambda关键字修饰的理解。

- super:在继承中充当父类的代理对象,在多继承中,super的调用顺序是MRO的顺序。

- pass:空语句,什么也不做,在特别的时候用来保证格式或是语义的完整性。

- yield:

- 1.保存当前运行状态(断点),然后暂停执行,即将函数挂起

- 2.将yeild关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用,当使用next()、send()函数让函数从断点处继续执行,即唤醒函数。

- lambda:定义匿名函数

写在最后:

好啦!今天的文章分享就到这里。想要获取更优质的干货、学习资料及圈内新鲜事儿,关注公粽号 速学Python,不错过圈内事。

猜你喜欢

转载自blog.csdn.net/qq_40196321/article/details/88089024