1. 一行代码生成[1,3,5,7,9,11,13,15,17,19]
使用列表生成式,创建列表,观察元素出现规律,代码如下:
1 | a = [ 2*i+1 for i in range(10)] |
2.写一个等差数列
产生一个首项为10,公差为12,末项不大于100的列表。
使用列表生成式创建:
1 | a = list(range(10,100,12)) |
3.一行代码求1到10000内整数和
提供两种方法
使用Python内置函数sum求和
1
2
3s = sum(range(10000))
s
49995000
使用functools模块中的reduce求和
1
2
3
4from functools import reduce
s = reduce(lambda x,y: x+y, range(10000))
s
49995000
4.打乱一个列表
使用random模块,shuffle函数打乱原来列表,值得注意是in-place打乱。
1 | import random |
5.字典按value排序并返回新字典
原字典:
1 | d = {'a':12,'b':50,'c':1,'d':20} |
使用Python的内置函数sorted
1 | d = {'a':12, 'b':50, 'c':1, 'd':20} |
6.如何删除list里重复元素,并保证元素顺序不变
给定列表:
1 | a = [3,2,2,2,1,3] |
如果只是删除重复元素,直接使用内置set函数,使用set函数是达到了去重目的,但是不能保证原来元素顺序。
1 | a = [3,2,2,2,1,3] |
下面的方法,列表删除某个元素后,后面的元素整体会向前移动。
1 | def del_duplicated(a): |
执行结果
1 | /Users/lvjing/PycharmProjects/python_base_project/venv/bin/python /Users/lvjing/PycharmProjects/python_base_project/interview_sample_01.py |
正确做法:
1 | def del_duplicated(a): |
执行结果
1 | /Users/lvjing/PycharmProjects/python_base_project/venv/bin/python /Users/lvjing/PycharmProjects/python_base_project/interview_sample_01.py |
7.怎么找出两个列表的相同元素和不同元素?
给定列表a=[3,2,2,2,1,3],列表b=[1,4,3,4,5],使用集合,找出相同元素:
1 | def ana(a, b): |
执行结果:
1 | /Users/lvjing/PycharmProjects/python_base_project/venv/bin/python /Users/lvjing/PycharmProjects/python_base_project/interview_sample_01.py |
8.字符串处理成字典
输入串"k0:10|k1:2|k2:11|k3:5",输出字典{k0:10,k1:2,....}
- 第一层split,根据分隔符
|,分割出k0:10,k1:2,k2:11,k3:5 - 第二层split,根据分隔符
:,分割出新字典的键值对
使用字典生成式,得到结果,也就是一个新字典:
1 | m = map(lambda x: x.split(':'), 'k0:10|k1:2|k2:11|k3:5'.split('|')) |
9.输入日子,判断这一天是这一年的第几天?
使用datetime模块,提取日期date对象,调用timeuple()方法,返回一个struct_time对象,属性tm_yday便是这一年的第几天:
1 | from datetime import datetime |
10.遍历目录与子目录,抓取.py文件
os模块、walk方法实现地柜遍历所有文件,os.path.splitext返回文件的名字和扩展名,如果扩展名匹配到ext,则添加到res中。
1 | import os |
11.单机4G内存,处理10G文件的方法?
假定可以单独处理一行数据,行间数据相关性为零。
方法一:使用Python内置模板,逐行读取到内存
使用yield,好处是解耦读取操作和处理操作
1
2
3
4def python_read(filename):
with open(filename, 'r', encoding='utf-8') as f:
for line in f:
yield line
以上每次读取一行,逐行 迭代,逐行处理数据
1
2
3
4if __name__ == '__main__':
g = python_read('./data/a.txt')
for c in g:
print(c)
缺点:逐行读入,频繁的IO操作拖累处理效率。那么,是否有一次IO,读取多行的方法呢?接下来查看方法二。
方法二:Pandas包中的read_csv函数
关于单机处理大文件,read_csv的chunksize参数能做到,设置为5,意味着一次读取5行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import pandas as pd
def pandas_read(filename, sep='', chunksize=5):
reader = pd.read_csv(filename, sep=sep, chunksize=chunksize, engine='python')
while True:
try:
yield reader.get_chunk()
except StopIteration:
print('---Done----')
break
if __name__ == '__main__':
g = pandas_read('./data/a.txt', sep="::")
for c in g:
print(c)
以上就是单机处理大文件的两个方法,推荐使用方法二,更加灵活。
12.统计一个文本中单词频次最高10个单词
使用yield解耦数据读取python_read和数据处理process
- python_read:逐行读入
- process:正则替换掉空字符,并使用空格,分隔字符串,保存到defaultdict对象中。
1 | import re |
使用两个函数,最后,使用Counter类统计出频次最高的10个单词:
1 | for line in python_read('./data/a.txt'): |
执行结果
1 | /Users/lvjing/PycharmProjects/python_base_project/venv/bin/python /Users/lvjing/PycharmProjects/python_base_project/interview_sample_01.py |
13.反转一个整数,例如-12345 -> -54321
- x位于(-10,10)间,直接返回,单个数字无需反转(反转结果一样)
- 将x转换为字符串对象str
- 若x是负数,截取sx[1:],并反转字符串
- 若x是正数,直接反转字符串
- 使用内置函数int()转化为整数
1 | def reverse_int(x: int): |
执行结果
1 | /Users/lvjing/PycharmProjects/python_base_project/venv/bin/python /Users/lvjing/PycharmProjects/python_base_project/interview_sample_01.py |
14.说明以下代码输出结果
此题需注意,内嵌函数foo使用的两个变量i和x,其中x为其形参,i为enclosing域内定义的变量。
扩展知识:enclosing作用域说明,看如下的例子
1 | def deco(func): |
从上面的例子看到,对于函数deco中wrapper函数中的print(str)的str查找感到迷惑。这时,就要提到Python作用域的LEGB原则。其中对E(Enclosing)作用域进行说明,在运行如下代码:
1 | print(foo.__closure__) |
打印出来的内存地址是什么呢?这就是上面wrapper函数引用的外层函数(deco)的两个变量:str和func。也就是说内层函数(wrapper)会把外层函数(deco)做用域里面的对象放到__closure__属性里,以供本身查找。可是不是全部外层函数作用域的对象都会放到内层函数的__closure__属性里,仅限本身用到的,这个__closure__就是enclosing作用域了。
rtn添加三个函数foo,但是并未发生调用。
1 | def f(): |
知道执行fs(10)时,内嵌函数foo才被调用,但是此时的enclosing变量i取值为3,所以输出结果为:
1 | /Users/lvjing/PycharmProjects/python_base_project/venv/bin/python /Users/lvjing/PycharmProjects/python_base_project/interview_sample_01.py |
15.如下函数foo的调用哪些是正确的?
1 | def foo(filename, a=0, b=1, c=2): |
已知filename为’.’,c为10,正确为foo函数传参的方法,以下哪些是对的,哪些是错误的?
- A-
foo('.', 10) - B-
foo('.', 0, 1, 10) - C-
foo('.', 0, 1, c=10) - D-
foo('.', a=0, 1, 10) - E-
foo(filename='.', c=10) - F-
foo('.', c=10)
分析:
- A 错误,a被赋值为10
- B 正确,c是位置参数
- C 正确, c是关键字参数
- D 错误,位置参数不能位于关键字参数后面
- E 正确,filename和c都是关键字参数
- F 正确,filename位置参数,c是关键字参数
验证测试:
1 | foo('.', 10) |
16.lambda函数的形参和返回值
key值为lambda函数,说说lambda函数的形参和返回值。
1 | def longer(*s): |
- lambda函数的形参:s解包后元素值,可能取值为:{1,3,5,7}、{1,5,7}、{2,4,6,7,8}三种。
- lambda函数的返回值为:元素的长度,可能取值为:{1,3,5,7}、{1,5,7}、{2,4,6,7,8}的长度是4,3,5。
17.正则匹配负整数
匹配所有负整数,不包括0。正则表达式:^-[1-9]\d*$
^-表示字符串以-开头[1-9]表示数字1到9,注意不要写成\d,因为负整数没有以-0开头的\d*表示数字0到9出现0次、1次货多次$表示字符串已数字结尾
以上分布讲解的示意图,如下所示:

测试字符串
1 | import re |
18.正则匹配负浮点数
正确写出匹配负浮点数的正则表达式,先要进行分析。
考虑到两个实例:-0.12、-111.234,就必须要分为两种情况。
适应实例-0.12的正则表达式:^-0.\d*[1-9]\d*$,注意要考虑到-0.0000这种非浮点数,因此正则表达式必须这样写。
以下几种写法都是错误的
^-0.\d*$^-0.\d*[1-9]*$^-0.\d*[0-9]*$
适应实例-111.234的正则表达式:^-[1-9]\d*.\d*$,使用|综合两种情况,故正则表达式为:
1 | ^-[1-9]\d*\.\d*|-0\.\d*[1-9]\d*$ |

测试字符串:
1 | import re |
19.使用filter()求出列表中大于10的元素
filter函数使用lambda函数,找出满足大于10的元素
1 | a = [15, 2, 7, 20, 400, 10, 9, -15, 107] |
20.以下map函数的输出结果
map函数当含有多个列表时,返回长度为最短列表的长度;
lambda函数的形参个数等于后面列表的个数。
1 | m = map(lambda x,y: min(x,y), [5, 1, 3, 4], [3, 4, 3, 2, 1]) |
21.以下reduce函数的输出结果
reduce实现对列表的归约化简,规则如下:
1 | f(x, y) = x*y + 1 |
因此,下面归约的过程为:
1 | f(1, 2) = 3 |
1 | from functools import reduce |
22.x=(i for i in range(5)),x是什么类型
x是生成器类型,与for等迭代,输出迭代结果:
1 | x = (i for i in range(5)) |
23.可变类型和不可变类型分别举例3个
- 可变类型:mutable type 常见的有:list、dict、set、deque等
- 不可变类型:immutable type 常见的有:int、float、str、tuple、frozenset等
只有不可变类型才能作为字典的键。
24.is和==有什么区别?
is用来判断两个对象的标识是否相等==用于判断值或内容是否相等,默认是基于两个对象的标识号比较。
也就是说,如果a is b为True且如果按照默认行为,意味着a==b也为True。
25.写一个学生类Student
添加一个属性id,并实现若id相等,则认为是同一位同学的功能。
重写__eq__方法,若id相等,返回True。
1 | class Student: |
判断两个Student对象,==的取值:
1 | s1 = Student(10, 'xiaoming') |
26.有什么方法获取类的所有属性和方法
获取下面类Student的所有属性和方法,使用dir()内置函数
1 | class Student: |
获取类上的所有属性和方法
1 | dir(Student) |
获取实例上的属性和方法
1 | s1 = Student(10, 'xiaoming') |
27.Python中如何动态获取和设置对象的属性
如下Student类:
1 | class Student: |
Python使用hasattr方法,判断实例是否有属性x:
1 | s1 = Student(10, 'xiaoming') |
使用setattr动态添加对象的属性,函数原型:
1 | <function setattr(obj, name, value, /)> |
为类对象Student添加属性
1 | if not hasattr(Student, 'address'): |
28.实现一个按照2*i+1自增的迭代器
实现类AutoIncrease,继承与Iterator对象,重写两个方法:
__iter____next__
1 | from collections.abc import Iterator |
执行结果
1 | /Users/lvjing/PycharmProjects/python_base_project/venv/bin/python /Users/lvjing/PycharmProjects/python_base_project/demo01.py |
29.实现文件按行读取和操作数据分离功能
使用yield解耦按行读取和操作数据的两步操作:
1 | def read_line(filename): |
30.使用Python锁避免脏数据出现的例子
使用多线程编程,会出现同时修改一个全局变量的情况,创建一把锁locka:
1 | import threading |
通过locka.acquire()获得锁,通过locka.release()释放锁。获得锁和释放锁之间的代码,只能单线程执行。
执行结果,如下:
1 | /Users/lvjing/PycharmProjects/python_base_project/venv/bin/python /Users/lvjing/PycharmProjects/python_base_project/demo03.py |
多线程的代码,由于避免脏数据的出现,基本退化为单线程代码,执行效率被拖累。
31.说说死锁、GIL锁、协程
- 死锁:多个子线程在系统资源竞争时,都在等待对方接触占用状态
- 比如:线程A等待线程B释放锁b,同时,线程B等待线程A释放锁a。在这何种局面下,线程A和线程B都相互等待着,无法执行下去,这就是死锁。
- GIL锁:为了避免死锁发生,Cython使用GIL锁,确保同一时刻只有一个线程在执行,所以其实是伪多线程。
- 协程:Python里常常使用协程技术来代替多线程。多进程、多线程的切换是由系统决定,而协程由我们自己决定。协程无需使用锁,也就不会发生死锁。同时,利用协程的协作特点,高效的完成了原编程模型只能通过多个线程才能完成的任务。