1.列出 5 个常用 Python 标准库?
os 操作系统
sys 命令行参数
re 正则
math 数学
time 时间
json 序列化
hashlib 摘要算法
logging 日志
random 随机数
threading 线程2.Python 内建数据类型有哪些?
int、bool、str、list、dict、tuple、set3.简述 with 方法打开处理文件帮我我们做了什么?
1、with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。
2、with语句即“上下文管理器”,在程序中用来表示代码执行过程中所处的前后环境 上下文管理器:含有__enter__和__exit__方法的对象就是上下文管理器。
3、__enter__():在执行语句之前,首先执行该方法,通常返回一个实例对象,如果with语句有as目标,则将对象赋值给as目标。
4、__exit__():执行语句结束后,自动调用__exit__()方法,用户释放资源,若此方法返回布尔值True,程序会忽略异常。
5、使用环境:文件读写、线程锁的自动释放等。4.列出 Python 中可变数据类型和不可变数据类型,为什么?
# 不可变数据类型:即数据被创建之后,数据的值将不再发生改变,有数值、字符、元祖类型。
# 可变数据类型:数据别创建之后,数据的值可以发生变化,有列表、字典、集合类型。5.Python 获取当前日期?
import datetime
datetime.datetime.now()6.统计字符串每个单词出现的次数
from collections import Counter
sentence = "I can because i think i can"
counts = Counter(sentence.split())
print(counts) # Counter({'can': 2, 'i': 2, 'I': 1, 'because': 1,'think': 1})7.用 python 删除文件和用 linux 命令删除文件方法
import os
os.remove("demo.txt")
rm demo.txt8.写一段自定义异常代码
raise ValueError("报错")9.举例说明异常模块中 try except else finally 的相关意义
try:
print('可能会出问题的代码块')
except 错误类型:
print('做一些处理')
else: # 可以不加else
print('上面的代码没有发生异常就执行')
finally:
print('一定要执行的代码')10.遇到 bug 如何处理
首先查看报错信息,根据报错信息找到相应代码,通常一般的数据结构或者算法错误只要找到报错代码就可以顺利解决。
如果遇到暂时不能解决的错误先不要慌,我们可以使用编译器的Debug模式或者自己在代码中加注断点进行代码排查。
如果依然不能解决bug,我们可以拷贝报错信息,在搜索引擎中进行搜索。
没有人写代码不出bug,如果你在一个bug上耗费时间超过半小时,可以与其他同事探讨(注意节制,可能有些费同事)。
另辟蹊径:方法总比困难多,在进行快速开发时,我们应该优先实现功能而不是拘泥于运行效率,所以遇到一些暂时不能解决的BUG可以考虑另外的实现方法。1.谈谈对 Python 和其他语言的区别
python是一门语法简洁,功能强大,应用领域广泛的强动态类型的解释型语言
与java比,java是静态类型
与c语言比,C运行速度快2.简述解释型和编译型编程语言
编译型:一次性将所有的代码转化为二进制,执行效率高,开发效率低,不能跨平台
解释型:逐行解释逐行运行,可以跨平台,开发效率高,执行效率低3.Python 的解释器种类以及相关特点?
cpython c写的
jpython java写的
pypy python写的
ipython 交互性解释器,基于cpython4.说说你知道的Python3 和 Python2 之间的区别?
py2 源码重复,混乱,冗余,不规范
py3 源码整合,优美,清晰,简单5.Python3 和 Python2 中 int 和 long 区别?
py2: 有整型和long长整型
py3: 全都是整型6.xrange 和 range 的区别?
Python2中使用xrange()来创建一个迭代器对象,使用range()创建一个list数组;
Python3中使用range()创建迭代器对象,移除了xrange()方法。7.什么是 PEP8?
PEP是 Python Enhancement Proposal 的缩写,翻译过来就是 Python增强建议书
PEP8 ,简单说就是一种编码规范,是为了让代码“更好看”,更容易被阅读。8.了解 Python 之禅么?
import this9.了解 docstring 么?
DocStrings 文档字符串是一个重要工具,用于解释文档程序,帮助你的程序文档更加简单易懂。
我们可以在函数体的第一行使用一对三个单引号 ''' 或者一对三个双引号 """ 来定义文档字符串。
你可以使用 __doc__(注意双下划线)调用函数中的文档字符串属性。
DocStrings文档字符串使用惯例:它的首行简述函数功能,第二行空行,第三行为函数的具体描述。10.了解类型注解么?
在Python3中新添加了“类型注解”特性,可以给参数、函数返回值和变量的类型加上注解,该注解仅仅是注释而已,对代码运行不会产生任何影响,真正的变量类型还是由Python解释器决定,你所做的只是提高代码可读性,并不会像静态语言中变量类型定义后就无法修改(强转除外)11.例举你知道 Python 对象的命名规范,例如方法或者类等
12.Python 中的注释有几种?
单行注释 #
多行注释使用三个单引号或者双引号13.如何优雅的给一个函数加注释?
""" """14.如何给变量加注释?
变量注释使用行内注释,根据pep8规范应该在代码后至少有两个空格,注释由#和一个空格开始15.Python 代码缩进中是否支持 Tab 键和空格混用。
尽量不混用16.是否可以在一句 import 中导入多个库?
可以,但是不介意。不便于阅读,搜索,编辑17.在给 Py 文件命名的时候需要注意什么?
避免关键字、库名、中文18.例举几个规范 Python 代码风格的工具
pylint、autopep819.列举 Python 中的基本数据类型?
int、bool、str、list、dict、tuple、set20.如何区别可变数据类型和不可变数据类型
可变,不可哈希,值变id不变
不可变,可哈希,值变id变21.将"hello world"转换为首字母大写"Hello World"
"hello world".title()22.如何检测字符串中只含有数字?
"".isdigit() # 该方法数字序号也算数字23.将字符串"ilovechina"进行反转
1.str[::-1]
2.
list_str = list(demo_str)
list_str.reverse()
print("".join(list_str))24.Python 中的字符串格式化方式你知道哪些?
f'{}'
"%s"%()
"{}".format25.有一个字符串开头和末尾都有空格,比如“ adabdw ”,要求写一个函数把这个字符串的前后空格都去掉。
.strip()
.replace(" ","")26.获取字符串”123456“最后的两个字符。
""[-2:]27.一个编码为 GBK 的字符串 S,要将其转成 UTF-8 编码的字符串,应如何操作?
S.decode('gbk').encode('utf-8')re.split("\W",demo_str)29.(1)怎样将字符串转换为小写
''.lower()(2)单引号、双引号、三引号的区别?
都可标识字符串
单、双引号混合使用可以避免转义符
三引号一般用于多行注释或多行文本30.已知 AList = [1,2,3,1,2],对 AList 列表元素去重,写出具体过程。
不保证顺序(会按照从小到大重新排序)
list(set(AList))
保证顺序
AList = [1, 2, 3, 1, 2]
result_list = []
for i in AList:
if i not in result_list:
result_list.append(i)
print(result_list)31.如何实现 “1,2,3” 变成 [“1”,“2”,“3”]
"".split(",")32.给定两个 list,A 和 B,找出相同元素和不同元素
# 找相同
same_list = [i for i in list_A if i in list_B]
print(same_list)
# 找不同
different_list = [i for i in list_A if i not in list_B]
print(different_list)33.[[1,2],[3,4],[5,6]]一行代码展开该列表,得出[1,2,3,4,5,6]
q = [[1,2],[3,4],[5,6]]
[e for i in q for e in i]34.合并列表[1,5,7,9]和[2,4,6,8]
a = [1,5,7,9]
a.extend([2,4,6,8])35.如何打乱一个列表的元素?
import random
random.shuffle(lis)36.字典操作中 del 和 pop 有什么区别
pop有返回值37.按照字典的内的年龄排序
d = [
{'name': 'alice', 'age': 38},
{'name': 'bob', 'age': 18},
{'name': 'ctrl', 'age': 28}
]
# 列表排序优先考虑sort
d.sort(key=lambda x:x['age'])38.请合并下面两个字典 a = {“A”:1,“B”:2},b = {“C”:3,“D”:4}
a.update(b)39.如何使用生成式的方式生成一个字典,写一段功能代码。
# 生成一个以姓名为键的字典,值为"student"
student_dic = {name: "student" for name in ["Robin", "Bob", "Jams"]}
print(student_dic)
# {'Robin': 'student', 'Bob': 'student', 'Jams': 'student'} 40.如何把元组(“a”,“b”)和元组(1,2),变为字典{“a”:1,“b”:2}
tuple_key = ("a", "b")
tuple_val = (1, 2)
result_dic = dict(zip(tuple_key,tuple_val))41.Python 常用的数据结构的类型及其特性?
42.如何交换字典 {“A”:1,“B”:2}的键和值?
demo_dic = {"A": 1, "B": 2}
# 使用字典推导式交换位置
result_dic = {v: k for k, v in demo_dic.items()}43.Python 里面如何实现 tuple 和 list 的转换?
tuple()
list()44.我们知道对于列表可以使用切片操作进行部分元素的选择,那么如何对生成器类型的对象实现相同的功能呢?
45.请将[i for i in range(3)]改成生成器
(i for i in range(3))46.a="hello"和 b="你好"编码成 bytes 类型
a.encode()
b.encode()47.下面的代码输出结果是什么?
a = (1, 2, 3, [4, 5, 6, 7], 8)
a[2] = 2报错,元祖是不可变类型,因此不能修改元祖内的值48.下面的代码输出的结果是什么?
a = (1, 2, 3, [4, 5, 6, 7], 8)
a[3][0] = 2 # (1, 2, 3, [2, 5, 6, 7], 8)
元祖是不可变数据类型,因此不能修改元祖中的值,但是如果元组中有可变数据类型,那么可以修改可变数据类型中的值,修改可变数据类型的值并不会使其内存id发生变化,所以元祖中元素中的内存id也没有改变,因此就做到了“修改元祖”操作。49.Python 交换两个变量的值
a, b = b, a50.在读文件操作的时候会使用 read、readline 或者 readlines,简述它们各自的作用
read:读取整个文件。
readline:读取下一行,使用生成器方法。
readlines:读取整个文件到一个迭代器以供我们遍历51.json 序列化时,可以处理的数据类型有哪些?如何定制支持 datetime 类型?
52.json 序列化时,默认遇到中文会转换成 unicode,如果想要保留中文怎么办?
import json
dict_demo = {"name": "旭东"}
# 使用dumps的默认参数ensure_ascii
print(json.dumps(dict_demo, ensure_ascii=False))53.有两个磁盘文件 A 和 B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件 C 中。
54.如果当前的日期为 20190530,要求写一个函数输出 N 天后的日期,(比如 N 为 2,则输出 20190601)。
55.写一个函数,接收整数参数 n,返回一个函数,函数的功能是把函数的参数和 n 相乘并把结果返回。
def out_func(n):
def in_func(num):
return n*num
return in_func
demo = out_func(3)
print(demo(4))56.下面代码会存在什么问题,如何改进?
from redis import Redis
rdb = Redis("127.0.0.1",6379,db=8)
rdb.get('key')64.请写一段 Python 连接 MySQL 数据库的代码。
import pymysql
# 打开数据库连接
db = pymysql.connect("localhost", "username", "password", "TESTDB", charset='utf8' )
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 使用execute方法执行SQL语句
cursor.execute("SELECT VERSION()")
# 使用 fetchone() 方法获取一条数据
data = cursor.fetchone()
# 关闭数据库连接
db.close()65.了解 Redis 的事务么?
事务提供了一种"将多个命令打包,一次性提交并按顺序执行"的机制,提交后在事务执行中不会中断。只有在执行完所有命令后才会继续执行来自其他客户的消息。
Redis通过multi,exec,discard,watch实现事务功能。
1. multi:开始事务
2. exec:提交事务并执行
3. discard:取消事务
4. watch:事务开始之前监视任意数量的键
5. unwatch:取消WATCH命令对多有key的监控,所有监控锁将会被取消。
关于ACID:
1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
2. 没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行
3. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制。66.了解数据库的三范式么?
属性不可分割:字段不能再分割,如“年级班级”可以分割为“年级”和“班级”两个字段
唯一主键:一张表中需要有一个唯一主键用来区分每行数据,如“学生学号 ”
消除冗余和传递依赖:不同表中不能存在重复的字段数据,如“学生”表中的“院系”字段和“班级”表中“院系”字段,我们可以关联两张表的字段而无需在“学生”表中再加一个“院系”。
详细解释请自行查找。67.了解分布式锁么?
在开发中可能会用到多线程和多进程,如果不同线程或者不同进程抢占同一个资源,对其行读写操作可能会导致数据不一致,导致数据不是在我们预想的情况下改变。这里为了保证线程或者进程安全,python中引入了线程锁和进程锁,保证了数据的一致性和完整性。
而为了保证分布式系统的数据安全,可以使用使用分布式锁来解决这一问题(秒杀场景)。分布式锁其实可以理解为:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。分布式锁的实现有很多种,常见的有redis、zookeeper和数据库mysql等。68.用 Python 实现一个 Reids 的分布式锁的功能。
69.写一段 Python 使用 Mongo 数据库创建索引的代码。
import pymongo
from pymongo import ASCENDING, DESCENDING
# 连接数据库,创建连接对象
myclient = pymongo.MongoClient(mongodbUrl)
# 切换数据库
mydb = myclient[dbName]
# 创建索引,create_index()创建索引,可以有多个约束条件,值为1则升序,-1是降序
mydb.create_index([("date", DESCENDING), ("author", ASCENDING)])70.函数装饰器有什么作用?请列举说明?
在不修改代码的前提下进行功能的扩展,装饰器完美遵循了开放封闭原则,即,对扩展是开放的,对修改是封闭的
eg:日志、执行时间、函数执行前后执行某功能等71.Python 垃圾回收机制?
引用计数为主,标记清除和分代回收为辅72.魔法函数__call__怎么使用?
__call__允许一个类的实例像函数一样被调用73.如何判断一个对象是函数还是方法?
类外声明的是函数
类中声明的是方法74.@classmethod 和@staticmethod 用法和区别
@classmethod 是类方法:访问和修改类属性,进行类相关的操作,通过类或示例对象调用,需要传递cls类对象为参数;
@staticmethod 是静态方法:不访问类属性和实例属性,通过类或实例调用,相当于一个普通函数。75.Python 中的接口如何实现?
类定义接口、函数定义接口76.Python 中的反射了解么?
77.metaclass 作用?以及应用场景?
metaclass允许创建或修改类,可以把类看成是metaclass创建出来的“实例”,它可以动态修改
应用:ORM78.hasattr() getattr() setattr()的用法
hasattr() 判断对象是否存在某个属性或方法
getattr() 获取对象属性或方法地址
setattr() 给对象的属性赋值,不存在就创建并赋值79.请列举你知道的 Python 的魔法方法及用途。
__new__ 创建一个空对象然后返回这个空对象
__init__ 负责将类进行实例化
__call__ 负责将对象转化为可执行对象,实现了该方法,就是可调用对象
__str__ 利用 print 函数打印一个对象时触发
__repr__ 当没有 __str__ 方法时触发 __repr__ 方法, 返回数据本身
__enter__() 和 __exit__() 只有支持上下文管理器的对象才能使用 with, 即在对象内实现了两个方法80.如何知道一个 Python 对象的类型?
type()81.Python 的传参是传值还是传址?
# 对可变对象(字典或列表)传址,对不可变对象(数字、字符或元祖)传值。
def demo_func(parm):
# 输出整数或者列表改变后的值
if isinstance(parm, int):
parm += 1
elif isinstance(parm, list):
parm.append(1)
print(parm)
if __name__ == '__main__':
int_parm = 1
# 函数内整数值修改(不可变类型不能修改值,其实这里是变量另外赋值)
demo_func(int_parm) # 输出为2
# 输出整数值,查看对象的值是否被修改
print(int_parm) # 输出为1,值未改变,说明传值
list_patm = [1,2,3]
# 函数修改列表
demo_func(list_patm) # 输出[1, 2, 3, 1]
# 查看函数外部列表是否发生改变
print(list_patm) # 输出[1, 2, 3, 1],列表发生改变,说明传址82.Python 中的元类(metaclass)使用举例 83.简述 any()和 all()方法
any()判断一个tuple或者list是否全为空,全空False, 不全为空返回True,空列表和空元祖为False;
all()判断一个tuple或者list是否全为非空,有一空则False, 全不空True,空列表和空元祖为True。84.filter 方法求出列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list(filter(lambda x: x % 2 == 1, a))85.什么是猴子补丁? 86.在 Python 中是如何管理内存的?
Python内存池:内存池的概念就是预先在内存中申请一定数量的,大小相等 的内存块留作备用,当有新的内存需求时,就先从内存池中分配内存给这个需求,不够了之后再申请新的内存。这样做最显著的优势就是能够减少内存碎片,提升效率。
python中的内存管理机制——Pymalloc:python中的内存管理机制都有两套实现,一套是针对小对象,就是大小小于256bits时,pymalloc会在内存池中申请内存空间;当大于256bits,则会直接执行new/malloc的行为来申请内存空间。
内存释放参考垃圾回收87.当退出 Python 时是否释放所有内存分配?
88.使用正则表达式匹配出
中的地址 a=“张明 98 分”,用 re.sub,将 98 替换为 100
import re
html_str = '<html><h1><div>a="张明 98 分"</div></html>'
result_str = re.sub(r'\d{2}', '100', html_str)
print(result_str) # <html><h1><div>a="张明 100 分"</div></html>89.正则表达式匹配中(.*)和(.*?)匹配区别?
(.*)贪婪匹配
(.*?)非贪婪匹配90.写一段匹配邮箱的正则表达式
^\w+@\w+(\.\w+)+$91.解释一下 python 中 pass 语句的作用? 92.简述你对 input()函数的理解 93.python 中的 is 和== 94.Python 中的作用域 95.三元运算写法和应用场景? 96.了解 enumerate 么? 97.列举 5 个 Python 中的标准模块 98.如何在函数中设置一个全局变量 99.pathlib 的用法举例 100.Python 中的异常处理,写一个简单的应用场景 101.Python 中递归的最大次数,那如何突破呢? 102.什么是面向对象的 mro 103.isinstance 作用以及应用场景? 104.什么是断言?应用场景? 105.lambda 表达式格式以及应用场景? 106.新式类和旧式类的区别 107.dir()是干什么用的? 108.一个包里有三个模块,demo1.py, demo2.py, demo3.py,但使用 from tools import 导入模块时,如何保证只有 demo1、demo3 被导入了。 109.列举 5 个 Python 中的异常类型以及其含义 110.copy 和 deepcopy 的区别是什么? 111.代码中经常遇到的args, **kwargs 含义及用法。 112.Python 中会有函数或成员变量包含单下划线前缀和结尾,和双下划线前缀结尾,区别是什么? 113.w、a+、wb 文件写入模式的区别 114.举例 sort 和 sorted 的区别 115.什么是负索引? 116.pprint 模块是干什么的? 117.解释一下 Python 中的赋值运算符 118.解释一下 Python 中的逻辑运算符 119.讲讲 Python 中的位运算符 120.在 Python 中如何使用多进制数字? 121.怎样声明多个变量并赋值?
122.已知:


(1) 从 AList 和 BSet 中 查找 4,最坏时间复杂度那个大? (2) 从 AList 和 BSet 中 插入 4,最坏时间复杂度那个大? 123.用 Python 实现一个二分查找的函数 124.python 单例模式的实现方法 125.使用 Python 实现一个斐波那契数列 126.找出列表中的重复数字 127.找出列表中的单个数字 128.写一个冒泡排序 129.写一个快速排序 130.写一个拓扑排序 131.python 实现一个二进制计算 132.有一组“+”和“-”符号,要求将“+”排到左边,“-”排到右边,写出具体的实现方法。 133.单链表反转 134.交叉链表求交点 135.用队列实现栈 136.找出数据流的中位数 137.二叉搜索树中第 K 小的元素
138.在 requests 模块中,requests.content 和 requests.text 什么区别 139.简要写一下 lxml 模块的使用方法框架 140.说一说 scrapy 的工作流程 141.scrapy 的去重原理 142.scrapy 中间件有几种类,你用过哪些中间件 143.你写爬虫的时候都遇到过什么?反爬虫措施,你是怎么解决的? 144.为什么会用到代理? 145.代理失效了怎么处理? 146.列出你知道 header 的内容以及信息 147.说一说打开浏览器访问 [百度一下,你就知道]获取到结果,整个流程。 148.爬取速度过快出现了验证码怎么处理 149.scrapy 和 scrapy-redis 有什么区别?为什么选择 redis 数据库? 150.分布式爬虫主要解决什么问题 151.写爬虫是用多进程好?还是多线程好? 为什么? 152.解析网页的解析器使用最多的是哪几个 153.需要登录的网页,如何解决同时限制 ip,cookie,session(其中有一些是动态生成的)在不使用动态爬取的情况下? 154.验证码的解决(简单的:对图像做处理后可以得到的,困难的:验证码是点击,拖动等动态进行的?) 155.使用最多的数据库(mysql,mongodb,redis 等),对他的理解?
156.TCP 和 UDP 的区别?
TCP UDP
是否连接 面向连接 面向非连接
传输可靠性 可靠 不可靠
应用场合 少量数据 传输大量数据
速度 慢 快157.简要介绍三次握手和四次挥手
三次握手:
TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答SYN+ACK,并对对方的 SYN 执行 ACK 确认。这种建立连接的方法可以防止产生错误的连接。
TCP三次握手的过程如下:
(1)客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
(2)服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
(3)客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。
四次挥手:
建立一个连接需要三次握手,而终止一个连接要经过四次握手,这是由TCP的半关闭(half-close)造成的。
TCP四次挥手的过程如下:
(1)TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
(2)服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
(3)服务器关闭客户端的连接,发送一个FIN给客户端。
(4)客户端发回ACK报文确认,并将确认序号设置为收到序号加1。158.什么是粘包? socket 中造成粘包的原因是什么? 哪些情况会发生粘包现象?
概念:
多个数据包被连续存储于连续的缓存中,在对数据包进行读取时由于无法确定发生方的发送边界
成因:
在发送端,由于两条消息发送的间隔时间很短,且两条消息本身也很短,在发送之前被合成一条消息
在接收端,由于接收不及时导致两条先后到达的信息在接收端黏在了一起
本质:
由于tcp协议流式传输的特点,导致数据与数据之间没有边界,主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
解决黏包:
借助一个模块,这个模块可以把要发送的数据长度转换成固定长度的字节。这样接收端每次接收消息之前只要先接受这个固定长度字节的内容看一看接下来要接收的信息大小,那么最终接受的数据只要达到这个值就停止,就能刚好不多不少的接收完整的数据了。159.举例说明 conccurent.future 的中线程池的用法 160.说一说多线程,多进程和协程的区别。 161.简述 GIL 162.进程之间如何通信 163.IO多路复用的作用? 164.select、poll、epoll 模型的区别? 165.什么是并发和并行? 166.一个线程 1 让线程 2 去调用一个函数怎么实现? 167.解释什么是异步非阻塞? 168.threading.local 的作用?
169.说说你知道的 git 命令 170.git 如何查看某次提交修改的内容