python面试题搜罗

本文整理了Python面试中常见的20个问题,涵盖字符串操作、列表处理、文件操作、排序、随机数生成、代码分析、GIL概念等,适合准备Python面试者参考学习。

本文为网络资源搜罗整理学习所得,持续更新

1.如何用Python来进行查询和替换一个文本字符串?

使用re模块中的sub()函数或者subn()函数来进行查询和替换

格式:sub(replacement, string[,count=0])(replacement是被替换成的文本,string是需要被替换的文本,count是一个可选参数,指最大被替换的数量)
>>> import re

>>>p=re.compile(‘blue|white|red’)

>>>print(p.sub(‘colour’,'blue socks and red shoes’))

colour socks and colourshoes

>>>print(p.sub(‘colour’,'blue socks and red shoes’,count=1))

colour socks and redshoes
subn()方法执行的效果跟sub()一样,不过它会返回一个二维数组,包括替换后的新的字符串和总共替换的数量

2.请写出一段Python代码实现删除一个list里面的重复元素

假设列表lst = [1, 3, 3, 2, 6, 2, 43, 5, 53, 4, 53, 3]

2.1 使用set函数:

>>>list(set(lst))

2.2 使用字典函数:

>>> b={}
>>> b=b.fromkeys(lst)
>>> c=list(b.keys())

2.3 循环判断处理:

>>> result = []
>>> for i in lst:
...     if i not in result:
...         result.append(i)

3.Python里面match()和search()的区别?

re模块中match(pattern,string[,flags]),检查string的开头是否与pattern匹配。

re模块中research(pattern,string[,flags]),在string搜索pattern的第一个匹配值。

4.Python里面如何生成随机数?

答:random模块

随机整数:random.randint(a,b):返回随机整数x,a<=x<=b

random.randrange(start,stop,[,step]):返回一个范围在(start,stop,step)之间的随机整数,不包括结束值。

随机实数:random.random( ):返回0到1之间的浮点数

random.uniform(a,b):返回指定范围内的浮点数。

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

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

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

6. 给定一个路径,请遍历输出:

import os  
def print_directory_contents(sPath):                                     
    for sChild in os.listdir(sPath):                
        sChildPath = os.path.join(sPath,sChild)
        if os.path.isdir(sChildPath):
            print_directory_contents(sChildPath)
        else:
            print sChildPath

7.如何用Python删除一个文件,copy一个文件?

  使用os.remove(filename)或者os.unlink(filename);

  shutil模块有一个copyfile函数可以实现文件拷贝
copyfile(src, dst)

8. 如何对列表进行间隔取值

lst[::num]#num为间隔数

cookie.使用netstat和awk命令来统计网络连接数

[root@ ~]# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S)print a,S[a]}'
ESTABLISHED 8
TIME_WAIT 31

9.如何对于一个多元组按某一项进行排序

>>> student_tuples = [
...     ('john', 'A', 15),
...     ('jane', 'B', 12),
...     ('dave', 'B', 10),
... ]
>>> sorted(student_tuples, key=lambda student: student[2])   # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

>>> from operator import itemgetter, attrgetter
>>>
>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

>>> def numeric_compare(x, y):
...     return x - y
>>> sorted([5, 2, 4, 1, 3], cmp=numeric_compare) 
[1, 2, 3, 4, 5]
Or you can reverse the order of comparison with:

>>>
>>> def reverse_numeric(x, y):
...     return y - x
>>> sorted([5, 2, 4, 1, 3], cmp=reverse_numeric) 
[5, 4, 3, 2, 1]

10. 使用一行代码求一个列表的和:

>>> reduce(lambda x,y:x+y,[1,2,3,4,5,6,4,3,2])

cookie
>>> x = map(lambda path:os.path.join('/etc',path),['a','b','c'])
>>> x
['/etc/a', '/etc/b', '/etc/c']

11. 赋值,浅拷贝,深拷贝的区别

>>> a=[1,2,3,4]
#变量=值
>>> b=a
>>> b is a and a is b
True
>>> b == a
True
>>> id(b),id(a)
(140139217122656, 140139217122656)

赋值:值是已经存在的,赋给哪个变量此变量就带上(指向)了这份值,可有多个变量指向一份值;针对这份值的修改会反映到任何一个变量上去(深层次可以通过id()函数来验证)

浅拷贝和深拷贝的不同仅仅是对组合对象来说,所谓的组合对象就是包含了其它对象的对象,如列表,类实例。而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。

浅拷贝:

所谓“浅拷贝”,是指创建一个新的对象,其内容是原对象中元素的引用。(拷贝组合对象,不拷贝子对象)

常见的浅拷贝有:切片操作、工厂函数、对象的copy()方法、copy模块中的copy函数。
>>> import copy
>>> b=copy.copy(a)
>>> b==a
True
>>> b is a
False
>>> a[0] = 'aaa'
>>> b
[1, 2, 3, 4]
>>> a
['aaa', 2, 3, 4]
>>> b[0]='bbbb'
>>> b
['bbbb', 2, 3, 4]
>>> a
['aaa', 2, 3, 4]
>>> id(b),id(a)
(140139217122656, 140139217122629)#id不同,但是看下边
>>> id(b[2]),id(a[2])
(32484408,32484408)#子条目的id是相同的

从上面可以明显的看出来,b 浅拷贝得到 a,a 和 b 指向内存中不同的 list 对象,但它们的元素却指向相同的对象。这就是浅拷贝!

深拷贝

所谓“深拷贝”,是指创建一个新的对象,然后递归的拷贝原对象所包含的子对象。深拷贝出来的对象与原对象没有任何关联。
如果子对象是不可变对象,则结果和上边的基本一致,但是实际上 a 和 b 是相互独立的,这是因为对于不可变对象,当需要一个新的对象时,python可能会返回已经存在的某个类型和值都一致的对象的引用
当子对象是可变对象的时候情况就会很明了了
>>> a=[[1,3],[4,6]]
>>> b=a
>>> a
[[1, 3], [4, 6]]
>>> b
[[1, 3], [4, 6]]
>>> b=copy.copy(a)
>>> b == a
True
>>> b is a
False
>>> b[0] is a[0]
True
>>> b = copy.deepcopy(a)
>>> b[0] is a[0]
False
>>> 

12. 请新建一个只有一个元素 1 的列表和元组。

lst = [1]
tup = (1,)

13. 通过两个列表生成一个字典:

>>> {k:v for k in x for v in y}

14. 嵌套列表降维:

>>> flattened = [i for row in matrix for i in row]

15. 获取一个相对路径的列表:

import os
files = [os.path.join('./my_dir', f) for f in os.listdir('./my_dir') if f.endswith('.txt')]

16.将csv文件读取为字典列表:

import csv
data = [ x for x in csv.DictReader(open('file.csv', 'rU'))]

DictReader类将会自动地使用csv文件的第一行作为字典的key属性名。DictReader类返回一个将会遍历csv文件所有行的对象。这个文件对象通过open()函数产生。我们提供了open()两个参数–第一个是csv文件名,第二个是模式。在这例子,‘rU’有两个意思。想往常一样,‘r’表示以读模式打开文件。‘U’表明我们将会接受通用换行符–‘n’,‘r’和‘rn’。

17.*args 和 **kwargs的区别

其实并不是必须写成*args 和**kwargs。 只有变量前面的 *(星号)才是必须的. 你也可以写成*var 和**vars. 而写成*args 和**kwargs只是一个通俗的命名约定。

*args 和 **kwargs 主要用于函数定义

*args 是用来发送一个非键值对的可变数量的参数列表给一个函数
**kwargs 允许你将不定长度的键值对, 作为参数传递给一个函数。 如果你想要在一个函数里处理带名字的参数, 你应该使用**kwargs。

18.看下面代码回答输出的结果是什么?为什么?

result = [lambda x: x + i for i in range(10)]
print(result[0](10))

这是一个结合了变量作用域、列表推导式和匿名函数的题目,较为复杂,比较考验Python基础知识掌握程度。有同学可能会回答10,其实答案是19,并且result[0~9](10)的结果都是19。

这是因为函数具有调用时才查找变量的特性。在你没调用它之前,它不会保存也不关心它内部变量的具体值。只有等到你调用它的时候,它才逐一去找这些变量的具体值。这里的result[0]被调用的时候,变量i已经循环完毕,变成9了,而不是想象中的动态0-9值。

那如果不想要这样的结果,想要i是循环的值怎么办?不要直接引用上层变量,把变量直接传进来。

result = [lambda x, i=i: x + i for i in range(10)]
print(result0)

19.Python 中的 GIL 是什么?全称?举个例子说说其具体体现。

GIL 全称 Global Interpreter Lock(全局解释器锁),任何 Python 线程执行前,必须先获得 GIL 锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。要避免这种“现象”利用操作系统的多核优势可以有下面几种方法:
使用 C 语言编写扩展,创建原生线程,摆脱 GIL,但是即使是扩展,在 Python 代码内,任意一条Python 代码还是会有 GIL 限制
使用多进程代替多线程,使用多进程时,每个进程都有自己的 GIL。故不存在进程与进程之间的 GIL 限制。但是多进程不能共享内存。

20. KISS

KISS原则(Keep It Simple,Stupid,Keep It Simple And Stupid)

应用题

手搓一个原生python实现的邮件发送程序:

#!/usr/bin/env python
#coding:utf-8
'''
file: email_send.py
date: 2018/1/27 10:14
author: lockey
email: iooiooi23@163.com
github: https://github.com/LockeyCheng
csdn: http://blog.youkuaiyun.com/Lockey23
github.io:https://lockeycheng.github.io/
desc: 
'''
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr


mail_host = "smtp.qq.com"
mail_user = "qq@qq.com"
mail_pass = "xxxxxxxxx"


sender = 'qq@qq.com'
receivers = ['receiver1@163.com','receiver2@163.com']


def mail_send():
    try:
        ret = True
        msg = MIMEText('mail content', 'plain', 'utf-8')
        msg['From'] = formataddr(["Lockey", sender])
        msg['To'] = formataddr(["To", receivers])
        msg['Subject'] = "subject"
        server = smtplib.SMTP_SSL(mail_host, 465)  #链接服务器     
        server.login(mail_user, mail_pass)#登录
        server.sendmail(sender, receivers, msg.as_string())#发送邮件
        server.quit()#退出
    except:
        print 'exception'
    return ret


if __name__ == '__main__':
    ret = mail_send()
    if ret:
        print("success!!!!!!")
    else:
        print("failed!!!!")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值