1、 简述 Python 的特点和优点
Python 是一门开源的解释性语言, 相比 Java C++ 等语言, Python 具有动态特性, 非常灵活。
2、 Python 有哪些数据类型?
Python 有 6 种内置的数据类型, 其中不可变数据类型是 Number(数字), String(字符串), Tuple(元组), 可变数据类型是 List(列表), Dict(字典), Set(集合)。
3、 列表和元组的区别
列表和元组都是可迭代对象, 能够对其进行循环、 切片等, 但元组 tuple 是不可变的。 元组不可变的特性, 使得它可以成为字典 Dict 中的键。
4、 Python 是如何运行的
Python 程序运行时, 会先进行编译, 将 .py 文件中的代码编译成字节码(bytecode), 编译结果储存在内存的 PyCodeObject 中, 然后由 Python 虚拟机解释运行。 当程序运行结束后, Python 解释器会将 PyCodeObject 保存到 pyc 文件中。每一次运行时 Python 都会先寻找与文件同名的 pyc 文件, 如果 pyc 存在则比对修改记录, 根据修改记录决定直接运行或再次编译后运行, 最后生成 pyc 文件 。
5、 Python 运行速度慢的原因
a). Python 不是强类型的语言, 所以解释器运行时遇到变量以及数据类型转换、比较操作、 引用变量时都需要检查其数据类型。
b). Python 的编译器启动速度比 JAVA 快, 但几乎每次都要启动编译。
c). Python 的对象模型会导致访问内存效率变低。 Numpy 的指针指向缓存区数据的值, 而 Python 的指针指向缓存对象, 再通过缓存对象指向数据。
6、 面对 Python 慢的问题, 有什么解决办法
a). 可以使用其他的解释器, 比如 PyPy 和 Jython 等。
b). 如果对性能要求较高且静态类型变量较多的应用程序, 可以使用 CPython。
c). 对于 IO 操作多的应用程序, Python 提供 asyncio 模块提高异步能力。
7、 描述一下全局解释器锁 GIL
每个线程在执行时候都需要先获取 GIL, 保证同一时刻只有一个线程可以执行代码, 即同一时刻只有一个线程使用 CPU, 也就是说多线程并不是真正意义上的同时执行。 但是在 IO 操作时, 是可以释放锁的(这也是 Python 能够异步的原因) 。 而且如果想要利用多核 CPU, 那么可以使用多进程。
8、 深拷贝 浅拷贝
深拷贝是将对象本身复制给另一个对象, 浅拷贝则是将对象的引用复制给另一个对象。 所以当复制后的对象改变时, 深拷贝的原对象值不会改变, 而浅拷贝原对象的值会被改变。
9、 is 和 == 的区别
is 表示的是对象标示符(object identity) , 而 == 表示的是相等(equality) 。
is 的作用是用来检查对象的标示符是否一致, 也就是比较两个对象在内存中的地址是否一样, 而 == 是用来检查两个对象是否相等。 但是为了提高系统性能,对于较小的字符串 Python 会保留其值的一个副本, 当创建新的字符串的时候直接指向该副本即可。 如:
a = 8
b = 8
a is b
10、 文件读写
简述文件读取时 read 、 readline、 readlines 的区别和作用
区别除了读取内容范围不同外, 返回的内容类型也不同。
read()会读取整个文件, 将读取到底的文件内容放到一个字符串变量, 返回 str 类型。
readline()读取一行内容, 放到一个字符串变量, 返回 str 类型。
readlines() 读取文件所有内容, 按行为单位放到一个列表中, 返回 list 类型。
11、 请用一行代码实现
请分别使用匿名函数和推导式这两种方式将 [0, 1, 2, 3, 4, 5] 中的元素求乘积,并打印输出元组。
print(tuple(map(lambda x: x * x, [0, 1, 2, 3, 4, 5]))) print(tuple(i*i for i in [0, 1, 2, 3, 4, 5]))
12、 请用一行代码实现
用 reduce 计算 n 的阶乘(n!=1× 2× 3× ...× n)
print(reduce(lambda x, y: x*y, range(1, n)))
13、 请用一行代码实现
筛选并打印输出 100 以内能被 3 整除的数的集合
print(set(filter(lambda n: n % 3 == 0, range(1, 100))))
14、 请用一行代码实现
text = 'Obj{"Name": "pic", "data": [{"name": "async", "number": 9, "price": "$3500"}, {"name": "Wade", "number": 3, "price": "$5500"}], "Team": "Hot"'
打印文本中的球员身价元组, 如 ($3500, $5500)
1. print(tuple(i.get("price") for i in json.loads(re.search(r'\[(.*)\]', 2. text).group(0))))
15、 请写出递归的基本骨架
def recursions(n): if n == 1: # 退出条件 return 1 # 继续递归 return n * recursions(n - 1)
16、 切片
请写出下方输出结果
tpl = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80,85, 90, 95]
print(tpl[3:]) print(tpl[:3]) print(tpl[::5]) print(tpl[-3]) print(tpl[3]) print(tpl[::-5]) print(tpl[:]) del tpl[3:] print(tpl) print(tpl.pop()) tpl.insert(3, 3) print(tpl) [15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95] [0, 5, 10] [0, 25, 50, 75] 85 15 [95, 70, 45, 20] [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95] [0, 5, 10] 10 [0, 5, 3]
17、 文件路径
打印输出当前文件所在目录路径
1. import os 2. print(os.path.dirname(os.path.abspath(__file__)))
打印输出当前文件路径
1. import os 2. print(os.path.abspath(__file__))
打印输出当前文件上两层文件目录路径
1. import os 2. print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
18、 请写出运行结果, 并回答问题
1. tpl = (1, 2, 3, 4, 5) 2. apl = (6, 7, 8, 9) 3. print(tpl.__add__(apl))
问题: tpl 的值发生变化了吗?
运行结果如下:
(1, 2, 3, 4, 5, 6, 7, 8, 9)
答: 元组是不可变的, 它是生成新的对象
19、 请写出运行结果, 并回答问题
name = ('James', 'Wade', 'Kobe') team = ['A', 'B', 'C'] tpl = {name: team}print(tpl) apl = {team: name}print(apl)
问题: 这段代码能运行完毕吗? 为什么? 它的运行结果是?
答: 这段代码不能完整运行, 它会在 apl 处抛出异常, 因为字典的键只能是不
可变对象, 而 list 是可变的, 所以不能作为字典的键。 运行结果是:
{('James', 'Wade', 'Kobe'): ['A', 'B', 'C']} TypeError
20、 装饰器
请写出装饰器代码骨架
def log(func): def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper
简述装饰器在 Python 中的作用:在不改动原函数代码的情况下, 为其增加新的功能。
21、 多进程 多线程
多进程更稳定还是多线程更稳定? 为什么?
多进程更稳定, 它们是独立运行的, 不会因为一个崩溃而影响其他进程。
多线程的致命缺点是什么?
因为所有线程共享进程的内存, 所以任何一个线程挂掉都可能直接造成整个进程
崩溃。
进程间通信有哪些方式?
共享变量、 队列、 管道。
摘自某《Python 面试武功秘籍.pdf》第一部分