Python最强面试手册——持续更新中2019.03.16

石墨文档链接(同步更新):https://shimo.im/docs/TZU3eFS0FBAeBXfX/

一、python基础

1.1 简述解释型和编译型编程语言?

概念:
编译型语言:把做好的源程序全部编译成二进制代码的可运行程序。然后,可直接运行这个程序。
解释型语言:把做好的源程序翻译一句,然后执行一句,直至结束。
区别:
编译型语言:执行速度快、效率高;依赖编译器、跨平台性差。如C、C++、Delphi
解释型语言:执行速度慢、效率低;依赖解释器、跨平台性好。如Java

1.2 Python解释器种类以及特点?

CPython:c语言开发的,使用最广的解释器
IPython:基于cpython之上的一个交互式计时器,交互方式增强,功能和cpython一样
PyPy:目标是执行效率,采用JIT技术,对python代码进行动态编译,提高执行效率
JPython:运行在Java上的解释器,直接把python代码编译成Java字节码执行
IronPython:运行在微软 .NET 平台上的解释器,把python编译成 .NET 的字节码

1.3 位和字节的关系?

位:“位(bit)”是电子计算机中最小的数据单位,每一位的状态只能是0或1。
字节:8个二进制位构成1个“字节(Byte)”,它是存储空间的基本计量单位。1个字节可以储存1个英文字母或者半个汉字,换句话说,1个汉字占用2个字节的存储空间。

1.4 b、B、KB、MB、GB的关系?

b——位(bit)
B——字节(Byte)
KB——千比特
MB——兆比特
GB——吉比特

1B = 8b 一个字节(byte)等于8位(bit)
1KB = 1024B
1MB = 1024KB
1GB = 1024MB

1.5 请至少列举5个PEP8规范

  • 每级缩进用4个空格
  • Python3 中不允许混合使用Tab和空格缩进
  • 限制所有行的最大行宽为79字符
  • 不要在一句import中多个库
  • 在核心Python发布的代码应该总是使用UTF-8
  • 推荐绝对路径导入,因为它们通常更可读

1.6 求结果:or and

v1 = 1 or 3
v2 = 1 and 3
v3 = 0 and 2 and 1
v4 = 0 and 2 or 1
v5 = 0 and 2 or 1 or 4
v6 = 0 or Flase and 1

结果:

v1 —— 1
v2 —— 3
v3 —— 0
v4 —— 1
v5 —— 1
v6 —— False

1.7 ascii、Unicode、utf-8.gbk区别?

ascii:把所有的字母的大小写,各种符号用二进制来表示,1bytes代表一个字符
Unicode:为了统一世界各国语言的不同,统一用2个bytes代表一个字符,特点:速度快,但浪费空间
utd8:为了改变Unicode的这种缺点,规定一个英文字符用一个字节表示,一个中文字符用三个字节表示,特点:节省空间,速度慢
gbk:是中文的字符编码,用2个字节代表一个字符

1.8 字节码和机器码的区别?

  • 机器码学名机器语言指令,有时也被称为原生码,是电脑的CPU可直接解读的数据
  • 通常意义上来理解的话,机器码就是计算机可以直接执行,并且执行速度最快的代码
  • 字节码是一种中间状态(中间码)的二进制代码(文件),需要直译器转译后才能成为机器码

1.9 三元运算编写格式

[on true] if [expression] else [on false]

如果表达式为True,就执行[on true]中的语句。否则,就执行[on false]中的语句

>>> a,b=2,3
>>> min=a if a>> min

运行结果:

2

1.10 列举你了解的所有Python2和Python3的区别?

  1. 性能
  • Py3性能比Py2性能慢15%,但还有很大的提升空间
  1. 编码
  • Py3源码文件默认使用utf-8编码
  1. 语法
  • 去除print语句
  • 关键词加入as 和with,还有True,False,None
  • 删除了raw_input,用input代替
  • 新的metaclass语法
  1. 字符串和字节串
  • 字符串只有str一种类型
  1. 数据类型
  • 只有一种整型——int
  • 新增bytes类型
  1. 面向对象
  • 迭代器的next()方法改名为next(),并增加内置函数next(),用以迭代器的next()方法

1.11 py2项目如何迁移成py3?

  1. 确定你的所有的依赖支持Python3
  2. 运行测试,确保你的所有的代码都能通过测试
  3. 进行代码迁移,这里你可能会用到一些工具
  4. six Python2 和 3 兼容库
  5. 利用 futurize 或者 modernize

Futurize就是在Python2中使用未来的Python3的功能,而Modernize正相反,使用Python2/3的兼容子集,利用six来提供兼容性。你可以选择任何一种方式。
c. 使用pylint 来分析代码中和Python3不兼容的地方。

  1. 当你组件迁移到Python3,你可能会使用tox来保证兼容2,tox支持创建不同的python环境来进行测试。
  2. 开始使用类型检查

1.12 用一行代码实现数值交换

a = 1
b = 2

解答:

a,b=b,a

1.13 Python3 和 Python2中int和long的区别

Python3中没有long,统一使用int

1.14 xrange 和 range 的区别

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

>>> range(5)
[0, 1, 2, 3, 4]
>>> range(1,5)
[1, 2, 3, 4]
>>> range(0,6,2)
[0, 2, 4]

xrange 用法与 range 完全相同,所不同的是生成的不是一个list对象,而是一个生成器。

>>> xrange(5)
xrange(5)
>>> list(xrange(5))
[0, 1, 2, 3, 4]
>>> xrange(1,5)
xrange(1, 5)
>>> list(xrange(1,5))
[1, 2, 3, 4]
>>> xrange(0,6,2)
xrange(0, 6, 2)
>>> list(xrange(0,6,2))
[0, 2, 4]

由上面的示例可以知道:要生成很大的数字序列的时候,用xrange会比range性能优很多,因为不需要一上来就开辟一块很大的内存空间。
xrange 和 range 这两个基本上都是在循环的时候用。

for i in range(0, 100): 
    print i 

for i in xrange(0, 100): 
    print i 

这两个输出的结果都是一样的,实际上有很多不同,range会直接生成一个list对象:

a = range(0,100) 
print type(a) 
print a 
print a[0], a[1] 

输出结果:


[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
0 1

而xrange则不会直接生成一个list,而是每次调用返回其中的一个值:

a = xrange(0,100) 
print type(a) 
print a 
print a[0], a[1] 

输出结果:


xrange(100)
0 1

但:
python2
xrange是生成器,range返回的是一个列表
python3
没有xrange了,range是生成器

1.15 如何实现字符串的反转?

方法一:切片,简单的步长为-1, 即字符串的翻转(常用)

s = 'hello'
a1=s[::-1]
print(a1)

方法二:reverse()函数

s = 'hello'
li=list(s)
li.reverse()
a2=''.join(li)
print(a2)

方法三:递归函数, 递归的方式, 每次输出一个字

def digui(s1):
    if s1 == "":
        return s1
    else:
        return digui(s1[1:]) + s1[0]

s = 'hello'
a3=digui(s)
print(a3)

1.16 文件操作时:xreadlines 和 readlines 的区别?

二者返回类型不同,xreadlines返回生成器,readlines返回列表
readlines() 读取文件所有内容,按行为单位放到一个列表中,返回list类型。
xreadlines()返回一个生成器,来循环操作文件的每一行。循环使用时和readlines基本一样,但是直接打印就不同

1.17 列举布尔值为False的常见值

‘’ False 0 [] () {}

1.18 列举字符串、列表、元组、字典每个常用的5个方法?

字符串:repleace,strip,split,reverse,upper,lower,join.....
列表:append,pop,insert,remove,sort,count,index.....
元组:index,count,__len__(),__dir__()
字典:get,keys,values,pop,popitems,clear,update,items.....

1.19 is 和 == 的区别?

a = 'lishi'
str1 = 'li'
str2 = 'shi'
str3 = str1 + str2
print("a == str3", a == str3)  # a == str3 True  ---> 只需要内容相等
print("a is str3", a is str3)  # a is str3 False ---> 只需要内存地址相等
print("id(a)",id(a))  # id(a)  38565848
print("id(str3)",id(str3))  #id(str3)  39110280

1.20 1、2、3、4、5能组成多少个互不相同且无重复的三位数

def threeNums():
    count = 0
    nums = []
    for index1 in range(1,6):
        for index2 in range(1,6):
            for index3 in range(1,6):
                if index1 != index2 and index1 != index3 and index2 != index3:
                    num = 100 * index1 + 10 * index2 + index3 
                    if num not in nums:
                        nums.append(num)
                        count += 1
    print (count)
    print (nums)
threeNums()

1.21 什么是反射?以及应用场景

反射就是以字符串的方式导入模块,以字符串的方式执行函数
注:getattr,hasattr,setattr,delattr对模块的修改都在内存中进行,并不会影响文件中真实内容。
应用场景:基于反射机制模拟web框架路由

1.22 简述Python的深浅拷贝?

浅拷贝只是增加了一个指针指向一个存在的地址
深拷贝是增加一个指针并且开辟了新的内存,这个增加的指针指向这个新的内存
采用浅拷贝的情况,释放内存会释放同一内存,深拷贝就不会出现释放同一内存的错误

1.23 Python 垃圾回收机制?

Python中垃圾回收的算法是采用 引用计数
为了解决对象的循环引用问题,Python引入了标记清除分代回收两种机制
参考链接:https://foofish.net/python-gc.html

1.24 Python 的可变类型和不可变类型的区别

可变数据类型:列表、字典、可变集合
不可变数据类型:数字、字符串、元组、不可变集合

1.25 求结果:

v = dict.fromkeys(['k1','k2'],[])   # {'k1':[],'k2':[]}
v['k1'].append(666)  # {'k1':[666],'k2':[666]}
print(v)
v['k1'] = 777  # {'k1':[777],'k2':[666]}
print(v)

结果:

{'k1':[666],'k2':[666]}
{'k1':777,'k2':[666]}

具体分析参见:https://blog.51cto.com/51enjoy/1735344

1.26 一行代码实现删除列表中重复的值

li = [1,1,2,2,33,3,4,5,6,3,2,7,8]
li = list(set(li))
print(li)  # [1, 2, 3, 4, 33, 5, 6, 7, 8]

1.27 如何实现"1,2,3"变成['1','2','3']

st = "1,2,3"
li = []
for s in st:
  if s.isdigit():
    li.append(str(s))
print(li)

1.28 如何实现['1','2','3']变成[1,2,3]

ls = ['1','2','3']
l2 = [int(l1) for l1 in ls]
print(l2)

1.29 比较:a = [1,2,3] 和 b = [(1),(2),(3)] 以及 c = [(1,),(2,),(3,)] 的区别

a,b列表中放的都是int类型的数据,而c列表里面放的是tuple(元组)类型的数据

1.30 如何用一行代码生成[1,4,9,16,25,36,49,64,81,100]?

li = [i*i for i in range(1,11)]

1.31 常用字符串格式化有哪几种?

'''
Python 中格式化有三种:
'''
# 需一个个的格式化
print('Hello %s' % ('Petrolero'))
# 不需要一个个的格式化,可以利用字典的方式,缩短时间
print('Hello %(name)s' % {'name':'petrolero'})
# 可读性强
print('Hello {name}'.format(name='petrolero'))

1.32 什么是断言(assert)?应用场景?

断言条件成立(True)则继续往下,否则抛出异常,一般用于:满足某个条件之后,才能执行,否则应该抛出异常,例:assert 1 == 0,'这是一个低级的错误'合约式设计是断言的经典应用,在一个正确的程序里,所有的前置条件和后置条件都将得到处理。

1.33 有两个字符串列表a 和 b,每个字符串是由逗号分隔的一些字符:

a = [ 
    'a,1',
    'b,3,22',
    'c,3,4'
]

b = [
    'a,2',
    'b,3,22,1',
    'c,3,4',
    'd,2'
]
按每个字符串的第一个值,合并a和b到c

c = [
    'a,1,2',
    'b,3,22,1',
    'c,3,4',
    'd,2'
]

答:

da = {x.split(',')[0]: x.split(',')[1:] for x in a}
db = {x.split(',')[0]: x.split(',')[1:] for x in b}
dc = {}
for k in set(list(da.keys()) + list(db.keys())):
    dc[k] = da.get(k, []) + [x for x in db.get(k, []) if x not in da.get(k, [])]
c = sorted([ ','.join([x, ','.join(dc[x])]) for x in dc])
print(c) #['a,1,2', 'b,3,22,1', 'c,3,4', 'd,2']

1.34 有一个多层嵌套的列表A=[1,2,[3,4,["434",...]]],请写一段代码遍历A中的每一个元素并打印出来

def fun(lst):
    for li in lst:
        if type(li) == list:
            return fun(li)
        else:
            print(li)
        
A=[1,2,[3,4,["434",5,6]]]
fun(A)

1.35 a = range(10),a[::-3]的结果是

range(9,-1,-3)

1.36 将列表内的元素,根据位数合并成字典

lst = [1,2,4,8,16,32,64,128,256,5129,1024,32769,65536]

#输出
{
  1:[1,2,4,8],
  2:[16,32,64],
  3:[128,256],
  4:[5129,1024],
  5:[32769,65536]
}

答:

lst = [1,2,4,8,16,32,64,128,256,5129,1024,32769,65536]
dic = {}

for i in lst:
    s = len(str(i))
    if s not in  dic:
        dic[s] = [i]
    else:
        dic[s].append(i)

print(dic)

你可能感兴趣的:(Python最强面试手册——持续更新中2019.03.16)