Python面试题(持续更新)

声明:题目来自老男孩,共315道;试着写写答案,证明下自己到底有多水OTZ。。。。。。

Part Ⅰ Python基础篇(80题)

1.为什么学习Python?
2.通过什么途径学习的Python?
略…
 
3.Python和Java、PHP、C、C#、C++等其他语言的对比?
执行过程上:Python为脚本语言,边解释边执行,而编译型语言需要编译完成后才能执行;在执行效率上脚本语言也就不如编译型语言快;
变量使用上:Python变量无需声明, 鸭子类型;C++等为强类型,变量使用前需声明;

 
4.简述解释型和编译型编程语言?
解释型语言在解释器下边解释边运行(动态),而编译型语言需要将源码交给编译器,经编译链接生产二进制可执行文件后,才能运行(静态)。
 
5.Python解释器种类以及特点?
CPython、IPython:用C语言开发,效率高,GIL,使用最广泛,IPython基于CPython,在交互方式上做了改进;
PyPy:PyPy是另一个Python解释器,它的目标是执行速度,PyPy采用JIT技术,对Python代码进行动态编译,所以可以显著提高Python代码的执行速度。
JPython:Jython是运行在Java平台上的Python解释器,可以直接把Python代码编译成Java字节码执行。无GIL
IronPython:IronPython是运行在微软.Net平台上的Python解释器,可以直接把Python代码编译成.Net的字节码。
 
6.位和字节的关系?
位(bit),字节(byte), 1Byte = 8bit
 
7.b、B、KB、MB、GB 的关系?
略…
 
8.请至少列举5个 PEP8 规范(越多越好)。
具体看这里
 
9.通过代码实现如下转换:

# 二进制转换成十进制:v = “0b1111011”# 十进制转换成二进制:v = 18# 八进制转换成十进制:v = “011”# 十进制转换成八进制:v = 30# 十六进制转换成十进制:v = “0x12”# 十进制转换成十六进制:v = 87
print(int('0b1111011', 2)) # 123
print(bin(18)) # 0b10010
print(int('011', 8)) # 9
print(oct(30)) # 0o36
print(int('0x12', 16)) # 18
print(hex(87)) # 0x57

10.请编写一个函数实现将IP地址转换成一个整数。

# 如 10.3.9.12 转换规则为:
#         10            00001010
# 3            00000011#          9            00001001
# 12            00001100# 再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ?

def func(s):
    l = s.split('.')
    ret = []
    for item in l:
        item = str(bin(int(item)))[2:]
        if len(item) < 8:
            n = 8 - len(item)
            item = ''.join(['0'*n, item])
        ret.append(item)
    print(ret)

    temp = ''.join(ret)
    print(temp)
    print(int(temp, 2))
    return ret

func('10.3.9.12')

11.python递归的最大层数?

def foo(n):
    print(n)
    n += 1
    foo(n)

foo(1) # 998

import sys
sys.setrecursionlimit(100000)

def bar(n):
    print(n)
    n += 1
    bar(n)

bar(1) # 3222左右

12.求结果:

v1 = 1 or 3
v2 = 1 and 3
v3 = 3 and 1 # 短路原则
v4 = 0 and 2 and 1
v5 = 0 and 2 or 1
v6 = 0 and 2 or 1 or 4
v7 = 0 or False and 1

print(v1, v2, v3, v4, v5, v6, v7)
# 1 3 1 0 1 1 False

13.ascii、unicode、utf-8、gbk 区别?
 
ascii 只支持英文字符 1字符1字节
unicode 通用编码,支持大部分语言,但比较占空间
utf-8 可变长编码,节省内存,ascii码是其子集
gbk 支持中文字符的编码

 
14.字节码和机器码的区别?
 
机器码是电脑CPU直接读取运行的机器指令,是电脑的CPU可直接解读的数据,运行速度最快,但是非常晦涩难懂,也比较难编写,一般从业人员接触不到;
字节码(Bytecode)是一种包含执行程序、由一序列 op 代码/数据对 组成的二进制文件。字节码是一种中间码,它比机器码更抽象,需要直译器转译后才能成为机器码的中间代码。
 
15.三元运算规则以及应用场景?
 
i = A if condition else B,主要运用与结构简单的条件语句,这样可以节省代码
 
16.列举 Python2和Python3的区别?
 

  1. print函数
  2. xrange和range
  3. raw_input和input
  4. 字符串编码: py2字符串其实是byte(默认已编码)
  5. 除法运算
  6. 延伸阅读 点这里

 
17.用一行代码实现数值交换:

    a = 1
    b = 2
    a, b = b, a

18.Python3和Python2中 int 和 long的区别?
Python 2有为非浮点数准备的intlong类型。int类型的最大值不能超过sys.maxint,而且这个最大值是平台相关的。可以通过在数字的末尾附上一个L来定义长整型,显然,它比int类型表示的数字范围更大。在Python 3里,只有一种整数类型int,大多数情况下,它很像Python 2里的长整型。由于已经不存在两种类型的整数,所以就没有必要使用特殊的语法去区别他们。延伸阅读点这里
 
19.xrange和range的区别?
 
在Python 2里,有两种方法来获得一定范围内的数字:range(),它返回一个列表,还有xrange(),它返回一个迭代器。在Python 3里,range()返回迭代器,xrange()不再存在了。
 
20.文件操作时:xreadlines和readlines的区别?
 
在Python 2里,文件对象有一个xreadlines()方法,它返回一个迭代器,一次读取文件的一行。这在for循环中尤其有用。
在Python 3里,xreadlines()方法不再可用了,可改为for line in a_file
 
21.列举布尔值为False的常见值?
 
主要有:0,空字符串,空元组,空列表,空字典等。
 
22.字符串、列表、元组、字典每个常用的5个方法?

str:
    find()
    replace()
    spilit()
    join()
    strip()
    ...
list:
    append()
    remove()
    pop()
    reverse()
    sort()
略....

23.lambda表达式格式以及应用场景?
 
格式:`lambda x: x+1
场景:配合map、reduce等高阶函数使用,或作为列表元素排序的key。
 
24.pass的作用?
 
空语句,什么也不做,占坑;
保证结构的完整性,可以以后实现。
 
25.*arg和**kwarg作用
 
实现了不定长传参,其中*args为可变长参数,允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple;**kw为关键字参数,允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
 
26.is和==的区别
 
is对比内存地址是否一致; == 对比值是否相等。
 
27.简述Python的深浅拷贝以及应用场景?
 
浅拷贝指仅仅拷贝数据集合的第一层数据,深拷贝指拷贝数据集合的所有层。对于只有一层的数据集合来说深浅拷贝的意义是一样的,比如字符串,数字,还有仅仅一层的字典、列表、元祖等。
 
对于 数字和字符串 而言,赋值、浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址。
 
场景: 数据完整备份(隔离)
 
28.Python垃圾回收机制?
 
Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题。通过“分代回收”(generation collection)以空间换取时间来进一步提高垃圾回收的效率。
Python中的垃圾回收机制
 
29.Python的可变类型和不可变类型?
 
数值类型(int和float)、字符串str、元组tuple都是不可变类型。而列表list、字典dict、集合set是可变类型。
 
不可变对象,变量对应内存的值不允许被改变,当变量要改变时,实际上是把原来的值复制一份后再改变,开辟一个新的地址,旧的地址上的数据被垃圾回收。
 
30.求结果:

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

31.求结果:

def num():
    return [lambda x:i*x for i in range(4)]

print([m(2) for m in num()])  # >>> [6, 6, 6, 6]
# 匿名函数m中,i只是一个变量,在匿名函数执行时才去查找,而这个时候,i已经变成3了;
# 若不想这样搞,可以让匿名函数中的i提升为函数的参数,这样在生成匿名函数时就绑定了每个i的值:
# def num():
#     return [lambda x, i=i:i*x for i in range(4)]
#
# print([m(2) for m in num()])

32.列举常见的内置函数?
这里写图片描述

33.filter、map、reduce的作用?
 
filter(function, sequence):对sequence中的item依次执行function(item),将执行结果为True的item组成一个List/String/Tuple(取决于sequence的类型)。
 
filter(function or None, sequence) -> list, tuple, or string:入参为函数和列表/元组/字符串,返回值为item列表/元组/字符串。
 
map(function, sequence) :对sequence中的item依次执行function(item),将执行结果function(item)组成一个List返回。
 
map(function, sequence[, sequence, …]) -> list:入参是为函数和列表/元组/字符串,返回值为function(item)列表。
 
reduce(function, sequence, starting_value):对sequence中的item顺序迭代调用function,如果有starting_value,还可以作为初始值调用。function接收的参数个数只能为2,先把sequence中第一个值和第二个值当参数传给function,再把function的返回值和第三个值当参数传给function,然后只返回一个结果。
 
reduce(function, sequence[, initial]) -> value:入参是为函数和列表/元组/字符串和初始值,返回值为数值。
 
34.一行代码实现9*9乘法表

print ("\n".join(["\t".join(["%s*%s=%s" %(x,y,x*y) for y in range(1, x+1)]) for x in range(1, 10)]))

35.如何安装第三方模块?以及用过哪些第三方模块?
 
在Python中,安装第三方模块,是通过setuptools这个工具完成的。Python有两个封装了setuptools的包管理工具:easy_install和pip。目前官方推荐使用pip。
 
36.至少列举8个常用模块都有那些?
 
pyqt、pymql、pygame、Django、Flask、opencv-python、pillow-python、Scrappy……
 
37.re的match和search区别?
 
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配,否则也返回None。
 
38.什么是正则的贪婪匹配?
 
重复运算符在默认条件下是贪婪的。

import re

pattern1 = r'\*(.+)\*'
r1 = re.findall(pattern1, r'*hello * *world!*')
print(r1)

pattern2 = r'\*(.+?)\*'
r2 = re.findall(pattern2, r'*hello * *world!*')
print(r2)

>>> ['hello * *world!']
>>> ['hello ', 'world!']
# 可见贪婪模式匹配了开始星号到结束星号间的全部内容,包括中间两个星号。

# 用(.+?)代替(.+)得到非贪婪模式,它会匹配尽可能少的内容。

39.求结果:

print([i % 2 for i in range(10)])
print((i % 2 for i in range(10)))
#######################################
# 一个是列表,一个是生成器:
# [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
# <generator object <genexpr> at 0x0000014F8B419410>

40.求结果:

print(1 or 2)  # 1 短路原则
print(1 and 2)  # 2
print(1 < (2==2))  # False
print(1 < 2 == 2)  # True !!!!!!
# 注意最后一个!

41.def func(a,b=[]) 这种写法有什么坑?
 
将可变对象作为默认参数,若多次调用时使用默认参数,默认参数会保留上次调用时的状态!
 
函数体内最好加上判断:if not b: b = []
 
42.如何实现 “1,2,3” 变成 [‘1’,’2’,’3’] ?
 
print("1,2,3".split(','))
 
43.如何实现[‘1’,’2’,’3’]变成[1,2,3] ?
 
print(list(map(lambda x:int(x), ['1', '2', '3'])))
 
44.比较: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 c = [(1,),(2,),(3,) ] 的区别?
 
a,b 均为整型列表, c为元组列表。
 
45.如何用一行代码生成[1,4,9,16,25,36,49,64,81,100] ?
 
print([i**2 for i in range(1,11)])
 
46.一行代码实现删除列表中重复的值 ?
 
print(list(set(l)))
 
47.如何在函数中设置一个全局变量 ?

def f():
    global x
    x = 1

f()
print(x)

 
不知道对不对,好像也可以直接用给函数加属性,是全局的:

def add(x=1):
    try:
        add.sum += x
    except AttributeError:
        add.sum = x
    return add.sum

print(add(3))
print(add(4))
print(add.sum)

48.logging模块的作用?以及应用场景?
 
日志记录,可以更好的管理我们的日志,并且可以将标准输入输出保存到日志文件,而且利用logging模块可以部分代替debug的功能,给程序排错。
 
场景:登录日志,错误日志等等
 
49.请用代码简单实现stack

class Stack:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return not len(self.items)

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def size(self):
        return len(self.items)

    def clear(self):
        self.items.clear()

50.常用字符串格式化哪几种?
 
%s,%d,%f
{} format格式化
 
51.简述 生成器、迭代器、可迭代对象 以及应用场景?
 
生成器应用场景:
在结果集比较大的情况下,可返回生成器以节省内存。如读取文件时….
 
52.用Python实现一个二分查找的函数。

l = list(range(10000))

def binary_search(seq, target_num):
    if len(seq) > 1:
        mid = int(len(seq)/2)
        if seq[mid] == target_num:
            print('find target number: %s'%target_num)
        elif seq[mid] < target_num:
            binary_search(seq[mid+1:], target_num)
        else:
            binary_search(seq[0:mid], target_num)
    else:
        if seq[0] == target_num:
            print('find target number: %s'%target_num)
        else:
            print('There is no such number!')


binary_search(l,111)

53.谈谈你对闭包的理解?
 
闭包 = 代码块 + 执行环境

  • 函数声明的时候,会生成一个独立的作用域
  • 同一作用域的对象可以互相访问
  • 作用域呈层级包含状态,形成作用域链,子作用域的对象可以访问父作用域的对象,反之不能;另外子作用域会使用最近的父作用域的对象
     

54.os和sys模块的作用?
 
os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口;sys模块负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境。

# os模块常用方法

os.remove(‘path/filename’) 删除文件
os.rename(oldname, newname) 重命名文件
os.walk() 生成目录树下的所有文件名
os.chdir('dirname') 改变目录
os.mkdir/makedirs('dirname')创建目录/多层目录
os.rmdir/removedirs('dirname') 删除目录/多层目录
os.listdir('dirname') 列出指定目录的文件
os.getcwd() 取得当前工作目录
os.chmod() 改变目录权限
os.path.basename(‘path/filename’) 去掉目录路径,返回文件名
os.path.dirname(‘path/filename’) 去掉文件名,返回目录路径
os.path.join(path1[,path2[,...]]) 将分离的各部分组合成一个路径名
os.path.split('path') 返回( dirname(), basename())元组
os.path.splitext() 返回 (filename, extension) 元组
os.path.getatime\ctime\mtime 分别返回最近访问、创建、修改时间
os.path.getsize() 返回文件大小
os.path.exists() 是否存在
os.path.isabs() 是否为绝对路径
os.path.isdir() 是否为目录
os.path.isfile() 是否为文件
# sys模块常用方法
sys.argv #命令行参数List,第一个元素是程序本身路径
sys.path #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.modules.keys() #返回所有已经导入的模块列表
sys.modules #返回系统导入的模块字段,key是模块名,value是模块
sys.exc_info() #获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息
sys.exit(n) #退出程序,正常退出时exit(0)
sys.hexversion #获取Python解释程序的版本值,16进制格式如:0x020403F0
sys.version #获取Python解释程序的版本信息
sys.platform #返回操作系统平台名称
sys.maxint # 最大的Int值
sys.stdout #标准输出
sys.stdout.write('aaa') #标准输出内容
sys.stdout.writelines() #无换行输出
sys.stdin #标准输入
sys.stdin.read() #输入一行
sys.stderr #错误输出
sys.exc_clear() #用来清除当前线程所出现的当前的或最近的错误信息
sys.exec_prefix #返回平台独立的python文件安装的位置
sys.byteorder #本地字节规则的指示器,big-endian平台的值是'big',little-endian平台的值是'little'
sys.copyright #记录python版权相关的东西
sys.api_version #解释器的C的API版本
sys.version_info #'final'表示最终,也有'candidate'表示候选,表示版本级别,是否有后继的发行
sys.getdefaultencoding() #返回当前你所用的默认的字符编码格式
sys.getfilesystemencoding() #返回将Unicode文件名转换成系统文件名的编码的名字
sys.builtin_module_names #Python解释器导入的内建模块列表
sys.executable #Python解释程序路径
sys.getwindowsversion() #获取Windows的版本
sys.stdin.readline() #从标准输入读一行,sys.stdout.write(a) 屏幕输出a
sys.setdefaultencoding(name) #用来设置当前默认的字符编码(详细使用参考文档)
sys.displayhook(value) #如果value非空,这个函数会把他输出到sys.stdout(详细使用参考文档)

55.如何生成一个随机数?
 
使用random模块
 
56.如何使用python删除一个文件?
 
os.remove('path/filename') # 删除文件
 
57.谈谈你对面向对象的理解?
 (看看左耳朵耗子的见解~)
面向对象编程是种具有对象概念的程序编程范型,同时也是一种程序开发的抽象方针。它可能包含数据、属性、代码与方法。对象则指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的可重用性、灵活性和可扩展性,对象里的程序可以访问及修改对象相关联的数据。在面向对象编程里,计算机程序会被设计成彼此相关的对象。
 
面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对计算机下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。
 
优点:

  • 能和真实的世界交相辉映,符合人的直觉。
  • 面向对象和数据库模型设计类型,更多地关注对象间的模型设计。
  • 强调于“名词”而不是“动词”,更多地关注对象和对象间的接口。
  • 根据业务的特征形成一个个高内聚的对象,有效地分离了抽象和具体实现,增强了可重用性和可扩展性。
  • 有大量非常优秀的设计原则和设计模式。
  • S.O.L.I.D(单一功能、开闭原则、里氏替换、接口隔离以及依赖反转,是面向对象设计的五个基本原则)、IoC/DIP……
     

缺点:

  • 代码都需要附着在一个类上,从一侧面上说,其鼓励了类型。
  • 代码需要通过对象来达到抽象的效果,导致了相当厚重的“代码粘合层”。
  • 因为太多的封装以及对状态的鼓励,导致了大量不透明并在并发下出现很多问题。
     

58.Python面向对象中的继承有什么特点?
 
继承更多了是为了多态,也可提升代码的复用程度。
特点:

  • 在继承中基类的构造(init()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用;
  • Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找);
     

59.面向对象深度优先和广度优先是什么?
 
当出现多重继承并产生菱形交叉时查找属性或方法路径顺序。
 
60.面向对象中super的作用?
 
super() 函数是用于调用父类(超类)的一个方法。
  super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
  MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
  Python3.x 和 Python2.x 的一个区别是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx
 
61.是否使用过functools中的函数?其作用是什么?
 

猜你喜欢

转载自blog.csdn.net/u010525694/article/details/80729404