1. 如何理解 python 中的深度拷贝和浅拷贝
浅拷贝旨在减少内存的占用,深拷贝可以在做数据的清洗、修改或者入库
的时候,对原数据进行复制一份,以防数据修改之后,找不到原数据。深浅拷
贝对于可变和不可变类型的数据不同。
不可变类型包括数值类型、字符串、布尔、None、元组
可变类型:列表、字典
对于不可变对象类型,没有深浅拷贝的说法,无论是深拷贝还是浅拷贝结
果一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。
对于可变类型来说,浅拷贝只复制容器,不复制容器中元素;深拷贝复制
容器,元素如果是可变类型,也复制元素
2. 请说说 get 请求与 post 请求的不同:
1.GET 表示从指定的服务器中获取数据 ,POST 表示提交数据给指定的服
务器处理
2.GET 查询的字符串参数显示在地址栏的 URL 中,请求参数是可见
的.POST 查询字符串不会显示在地址栏中,请求参数是不可见的
3.GET 请求能够被缓存,POST 请求不能被缓存下来
4.GET 请求会保存在浏览器的浏览记录中,POST 请求不会保存在浏览器浏
览记录中
5.GET 请求有长度限制,POST 请求没有长度限制
6.GET 查询的字符串参数会显示在地址栏的 URL 中,不安全,请不要使用
GET 请求提交敏感数据
POST 请求数据不会显示在地址栏中,也不会缓存下来或保存在浏览记录
中,所以 POST 请求比 GET 请求安全,但也不是最安全的方式。如需要传送
敏感数据,请使用加密方式传输
3. python2 和 python3 的区别
object 则创建新式类。Python3 中则移除了旧式类,默认创建新式类。
第二、python2 中字节字符串类型为 str,文本字符串类型为 Unicode
python3 中字节字符串类型为 bytes,文本字符串类型为 str
第三、python2 中直接赋值即可声明元类,python3 中则通过 class 关键字
声明元类
第四、一些 python2 中的类库,在 python3 中进行了合并,如 StringIO 和
cStringIO 合并为 IO 等
第五、python2 中默认的字符串类型默认是 ASCII 编码,python3 中默认的
字符串类型是 Unicode 编码,无论字节数占用大小,均占用字符串的一个下标。
第六、python2 中,print 是个特殊语句,python3 中 print 是函数
第七、python2 中单斜杠除法运算的结果是整型,python3 中是浮点类型,
如 3 通过单斜杠除号除以 2,在 python2 中等于 1,在 python3 中等于 1.5
第八、python2 中异常链会丢失原始异常信息,python3 中可以显式指定一
个异常作为另一个异常的子句
第九、python2 中的 dict 类中的 keys、values 和 items 属性均返回 list 对
象,iterkeys、itervalues 和 iteritems 返回生成器对象。
python3 中移除了 list、只返回一个生成器的对象。
第十、python3 中需要使用 from 进行相对导入,python2 中仅要求不写路
径即可
4. Python 中 classmethod 与 staticmethod 的区别
对象共有;但 classmethod 有参数 cls,这个参数是类对象,由系统自动传
递;staticmethod 没有类对象参数。
classmethod 在一些工厂类的情况下使用较多,也就是说 OOP 里继承的
时候使用,staticmethod 一般情况下可以替换为外部的函数,后者继承的时
候不可更改,和 C++/JAVA 中的静态方法很相似
5. 如何在不改变原有 list 顺序的前提下,去除该 list 中的重复代码
1, 使用循环实现
2, 使用列表生成式
3, 使用排序实现
6. 请说说,python 中不同类型的数据变量在内存中是如何存储的
python 中一切皆对象,对象的存储,采用了引用语义的方式;系统会保
存对象的引用数量,当某个对象的引用数量为 0 时,对象会被回收。
变量定义: a = 3 在这里 3 就是一个整型对象,3 这个对象的地址保存
到变量 a 中,变量存储的只是一个对象的内存地址,而不是这个对象本身
变量保存了对象的地址,也称变量引用了对象
7. 请解释 with 关键字的用法
上下文管理器:上下文管理器对象实现了__enter__() 和 __exit__() 方法。
__enter__() 方法在语句体执行之前进入上下文时执行 ,__exit__() 在语句体
执行完后从上下文退出时执行。
with 语句支持运行时上下文这一概念。
语法:with 表达式 [as 变量]:
语句体
作用:经常用于保存和恢复各种全局状态,锁定和解锁资源,关闭打开的
文件等。
例子:with open('1.txt') as fp:
for line in fp:
prin(line)
这里使用了 with 语句,不管在处理文件过程中是否发生异常,都能保证
with 语句执行完毕后已经关闭了打开的文件句柄。如果不用 with 语句,
则要使用 try-except-finally 处理,语法变的复杂。
8. 请说说 python 中正则表达式如何提取数据
利用正则表达式来提取想要的内容要使用分组。
分组就是用一对圆括号“()”括起来的正则表达式,匹配出的内容就表示
一个分组。从正则表达式的左边开始看,看到的第一个左括号“(”表示第一
个分组,第二个表示第二个分组,依次类推,需要注意的是,有一个隐含的全
局分组(就是 0),就是整个正则表达式。
要想提取数据,首先你需要写出正确的正则表达式,在表达式中把要提取
的内容使用分组括起来;然后执行 match 或 search 匹配;匹配后使用 group
(num)和 groups 方法获取提取内容, 也可以使用 findall()
9. 请说说 python 中 list,set,dict,tuple 的区别
list 和 tuple 区别:
1)list 用[]定义,tuple 用()定义
2)list 是可变容器,可以修改其中的元素,tuple 属于不可变容器,不能
修改元素。
3)tuple 属于不可变容器,没有深复制和浅复制,list 有深复制和浅复制
4)list 一般不做函数参数的默认值,tuple 可以做函数参数的默认值
dict 和 set 区别:
1)dict 可以通过 key 访问,set 不行
2)dict 键不可以重复,值可以重复,set 不允许有重复元素
3)dict 可以根据键修改值,set 不能修改元素```
####10.请说说队列与栈两种数据结构如何实现
```栈:后进先出,可以使用列表实现,只需要把操作固定到列表一端,这个
列表就可以当栈使用
队列:先进先出,可以使用列表实现,在一端固定插入元素,在另外一端
删除元素就可以实现队```
####11.请说说 python 中*args 与**kwargs 的用法与区别
```python 的函数参数可以有多种形式,其中如果要接收任意多个位置参
数,可以将参数声明为*args,其中 args 只是变量名字,可以是任何合法变量
名,例如函数 def demo(*args);可以接收以下传参:
demo(1)
demo(1,2)
demo(1,2,3,4)
如果函数形参声明为**kwargs,则表示函数可以接收任意关键字参数,
比如 def test(**kwargs),则可以有如下调用方式:
test(a=1)
test(a=1,b=3)
test(a=1,b=5,d=100)
区别:
1)*args 中 args 是元组,可以通过 args 元组获取所有位置参数
2)**kwargs 中的 kwargs 是字典,可以通过 kwargs 获取所有关键
字参数.
3)在函数的形参中,如果同时有*args 和**kwargs,*args 必须在
**kwargs 前面.
12.请说说 python 中 type 函数与 isinstance() 的区别
是指定类型
2, 返回值不同: type 返回类型,isinstance 返回 True 或 False
3, type 不能判断子类对象是否属于父类,而 isinstance 可以
13.请叙述下 python 如何复制一个大文件
1)打开源文件(读)和目标文件(写)
2)从源文件中读取指定大小的字节,比如 1024,将其写入目标文件
3)重复 2)直到源文件读完
4)关闭源文件和目标文件
def mycopy(src_file, dst_file):
try:
with open(src_file, "rb") as fr, open(dst_file, 'wb') as fw:
while True:
data = fr.read(1024)
if not data:
break
fw.write(data)
except OSError:
print("打开读文件失败")
except:
print("可能 U 盘被拔出...")```
####14.请解释下什么是解释性语言,什么是编译性语言
```编译型语言:编译型语言写的程序执行之前,需要一个专门的编译过程,
把程序编译成机器语言文件;比如,exe 文件,以后运行的话就不用重新编译
了,直接运行;因为翻译只做了一次,运行时不需要编译,所以编译型语言
的程序执行效率高!
解释型语言:解释型语言的程序不需要编译,省了道工序,解释型语言在
运行程序的时候才翻译,比如解释型 basic 语言,专门有一个解释器能够直接
执行 basic 程序,每个语句都是执行的时候才翻译;这样解释型语言每执行一
次就要翻译一次,效率比较低。但是解释型语言跨平台性比较好,因为他依赖
解释器,只要平台装有解释器程序就行。
15.请简单的叙述下数据存储原理
(1)顺序存储方法
该方法把逻辑上相邻的结点存储在物理位置上相邻的存储单元里,结点间的
逻辑关系由存储单元的邻接关系来体现。由此得到的存储表示称为顺序存储
结构 (Sequential Storage Structure ),通常借助程序语言的数组描述。
该方法主要应用于线性的数据结构。非线性的数据结构也可通过某种线性化
的方法实现顺序存储。
(2)链接存储方法
该方法不要求逻辑上相邻的结点在物理位置上亦相邻,结点间的逻辑关系由
附加的指针字段表示。由此得到的存储表示称为链式存储结构(Linked
Storage Structure), 通常借助于程序语言的指针类型描述。
(3)索引存储方法
该方法通常在储存结点信息的同时,还建立附加的索引表。索引表由若干索
引项组成。索引项的一般形式是:(关键字、地址)。关键字是能唯一标识一个
结点的那些数据项。
(4)散列存储方法
该方法的基本思想是:根据结点的关键字直接计算出该结点的存储地址。
16.请说下您平时是怎么调错的
1)print 调错:把所有可能出错的变量都打印出来,看看是哪段代码出错。
用 print 最大的坏处是将来还得删掉它
2)assert 断言调试:凡是用 print 来辅助查看的地方,都可以用断言
(assert)来替代。如果断言失败,assert 语句本身就会抛出 AssertionError,
不过,启动 Python 解释器时可以用-O 参数来关闭 assert。关闭后,你可以把所
有的 assert 语句当成 pass 来看。
3)可以启动 Python 的调试器 pdb 让程序以单步方式运行,可以随时查看运
行状态。
4)使用 IDE 调试:可以使用 pycharm、pydev 等集成开发环境设置断点,
单步调试。
17.请说说 python 中 while-else/for-else 语法的用法
while-else:
while 表达式:
循环体
else:
【else 语句块】
说明:当 while 语句执行完成之后,执行【else 语句块】,如果用 break
跳出循环则不执行 else
for-else:
for x in 表达式:
循环体
else:
【else 语句块】
说明:当 for 语句执行完成之后,执行【else 语句块】,如果用 break
跳出循环则不执行 else
18.请说说 python 中的作用域是怎样划分的
概念:变量的作用域指的是变量在那段代码中可以使用,可以使用变量的那段
代码就是变量的作用域。在 python 中,只有函数/类/模块才引入作用域,
if/elif/else , while/for,try/except 等并不会引入新的作用域
作用域按从小到大顺序可以分为:
局部作用域:在函数内部定义,从定义开始到本函数结束
闭包作用域:外部函数定义的变量,范围从定义开始到外部函数结束,可
以在闭包函数内直接使用,在整个程序运行过程中都存在
全局作用域:在所有函数外定义,范围从定义开始到本文件结束
内建作用域:python 系统内定义的函数、类等,可以在任何位置直接使用```
####19.请说说你是如何理解 python 中的封装,继承,多态的
```封装:封装就是把对象的属性和行为结合成一个独立的整体,把内部的实
现细节隐藏起来,不能被外界所看见,调用的人只能执行,而看不到实现的
细节,保证了代码的安全性
继承:从已有类中派生出新的实例对象,子类继承父类的属性和方法,并
且自己可以拓展出自己独有的属性和方法。保证了代码的复用率。python 支
持单继承和多继承。
多态:首先 Python 不支持多态,也不用支持多态,python 是一种多态
语言,崇尚鸭子类型。在鸭子类型中,关注的不是对象的类型本身,而是它是
如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它
接受一个类型为鸭的对象,并调用它的走和叫方法。在使用鸭子类型的语言
中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。
如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这
样的正确的走和叫方法的对象都可被函数接受的这种行为引出了以上表述,这
种决定类型的方式因此得名。
20.请从 socket 编程的角度谈谈网络请求的流程
网络请求是基于 HTTP 协议的,但 http 协议只是一个应用层协议,它底
层是通过 TCP 进行传输数据的。因此,浏览器访问 Web 服务器的过程必须先
有“连接建立”的发生。浏览器向 Web 服务器发出 Http 请求以及 Web 服务
器给浏览器回复的过程如下:
1)浏览器创建 Socket,按给定 IP(域名)和端口(默认为 80)连接服
务器。
2)连接成功后,浏览器依据 HTTP 协议规范,向 Web 服务器发送请求
数据,会使用类似 Socket.Send()、Socket.BeginSend()等方法。
3)浏览器等待服务器处理并返回数据;
4)Web 服务器端使用 Socket.Accept()、Socket.BeginAccept()等方法
侦听到浏览器的连接后,便开始接收浏览器发送的数据。接收到请求数据后,
依据 HTTP 协议规范解析数据,然后处理,最终将处理结果发回给浏览器,这
里可能用到类似 Socket.Send()、Socket.BeginSend()等方法;
5)Web 服务器发送完处理结果后,关闭 Socket;
6)浏览器接收 Web 服务器发回的数据(如 html),将其显示在浏览器
UI 界面。关闭 socket;
7)一次“浏览器到 Web 服务器”的 http 请求结束;
21.请说说 TCP 与 UDP 编程的区别
1.TCP 是面向连接的,即每次收发数据之前必须通过 connect 建立连
接,也是双向的,即任何一方都可以收发数据,协议本身提供了一些保障机
制保证它是可靠的、有序的,即每个包按照发送的顺序到达接收方。
UDP 它是无连接的,不可靠的,因为通讯双方发送数据后不知道对方是
否已经收到数据,是否正常收到数据。
任何一方建立一个 socket 以后就可以用 sendto 发送数据,也可以用
recvfrom 接收数据。根本不关心对方是否存在,是否发送了数据。
它的特点是通讯速度比较快。大家都知道 TCP 是要经过三次握手的,而
UDP 没有。
2.TCP 对系统资源的要求较多,UDP 相对较少
3.TCP 程序结构复杂,UDP 程序结构较简单
4.TCP 以流模式传输数据与,UDP 以数据报模式传输数据
5.TCP 能够保证数据正确性,UDP 则可能丢包
6.TCP 能过保证数据顺序,UDP 则不保证
22.请说说 python 中高阶函数的思想
请说说你对 python 中高阶函数的认识:
高阶函数指的是能接收函数作为参数的函数;python 中有一些内置的高
阶函数,在某些场合使用可以提高代码的效率
1. map 函数:接收一个函数和一个序列,map 将传入的函数依次作用到
序列的每个元素,并且把结果作为新的列表返回.所以 map 函数可以方便将一
个序列中的每一个元素做统一处理.
2.reduce 函数:接收一个函数和一个序列,把一个函数作用到一个序列
上,这个函数必须接收两个参数,reduce 把结果和序列的下一个元素做累积
计算.所以 reduce 函数可以方便将一个序列中的所有元素做累计处理.
3.filter 函数:接收一个函数和一个序列,把传入的函数依次作用于每个
元素,然后根据返回值是 True 还是 False 决定保留还是丢弃该元素. 所以
filter 函数可以方便的过滤掉序列的无用元素.
23.请说说迭代器与可迭代对象的区别及迭代器的好处
请说说迭代器与可迭代对象的区别及迭代器的优点:
1.可迭代对象: 可迭代对象并不是一种具体的数据类型,只要可以直接用于
for⋯in⋯循环遍历的对象都是可迭代对象,比如:list,tuple,dict,set,str
等等。
2.迭代器:可以被 next()函数调用并不断返回下一个值的对象称为迭代器:
Iterator。它们表示一个惰性计算的序列;
迭代器优点:使用迭代器不要求事先准备好整个迭代过程中的所有元素。
迭代器仅仅在迭代到某个元素时才计算该元素,
而在这之前或之后元素可以不存在或者被销毁。比起使用列表等容器存
储,更加省内存,因此迭代器适合遍历一些数量巨大甚至无限的序列。
24.请说说装饰器的好处,什么情况下使用,以及如何实现一个通用装饰器
1.装饰器的实现是由闭包支撑的;
2.装饰器本质上是一个 python 函数,它可以在让其他函数在不需要做任何代
码的变动的前提下增加额外的功能;
3.装饰器的返回值也是一个函数的对象,该函数对象就是添加额外功能后的与
原函数同名的函数.
通用装饰器:
# 装饰器; 在不修改源代码的基础上,添加新的功能
def outer(functionName):
def inner(*args, **kwargs):
print("-----添加功能-----")
ret = functionName(*args, **kwargs)
print("-----添加功能-----")
return ret
return inner
25.请说说线程什么情况下需要加锁, 及其优缺点
加锁原因: 如果有多个线程同时操作一个对象,如果没有很好地保护该对
象,会造成程序结果的不可预期
比如:我们在每个线程的 run 方法中加入一个 time.sleep(1),并同时输出
线程名称,则我们会发现,输出会乱七八糟。
因为可能我们的一个 print 语句只打印出一半的字符,这个线程就被暂
停,执行另一个去了,所以我们看到的结果很乱,这种现象叫做“线程不安
全”
解决:
Threading 模块为我们提供了一个类 Threading.Lock 锁。我们创
建一个该类对象,在线程函数执行前,“抢占”该锁,执行完成后,“释放”
该锁, 则我们确保了每次只有一个线程占有该锁。这时候对一个公共的对象
进行操作,则不会发生线程不安全的现象了。
锁的优点: 使得数据能安全的进行操作
锁的缺点:
1.如果多个线程要调用多个对象,而 A 线程调用 A 锁占用了 A 对
象,B 线程调用了 B 锁占用了 B 对象,A 线程不能调用 B 对象,B 线程不
能调用 A 对象,于是一直等待。这就造成了线程“死锁”
2.如果多个线程要调用同一个对象,A 线程调用 A 锁占用了 A 对
象,B 线程也需要使用 A 对象,A 线程不释放 A 对象,B 线程就不能调用 A 对
象,B 线程会等待 A 线程释放后才能使用,所以效率低下
26.请谈谈 python 中的协程的运用
1.协程就是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问
题而耗费许多切换时间, 而协程就是用户自己控制切换的时机,不再需要陷入系统
的内核态。
2.协程的执行效率非常高。因为子程序切换不是线程切换,而是由程序自身控
制,因此,没有线程切换的开销.和多线程相比, 线程数量越多相同数量的协程体
现出的优势越明显
3.协程不需要多线程的锁机制。由于只有一个线程,也不存在同时写变量的冲
突,在协程中控制共享资源不需要加锁,只需要判断数据的状态, 所以执行效率
远高于线程,对于多核 CPU 可以使用多进程+协程来尽可能高效率地利用 CPU
27.请说说计算机中使用缓存的好处
从系统的层面说,CPU 的速度远远高于磁盘 IO 的速度;所以要想提高响
应速度,必须减少磁盘 IO 的操作,但是有很多信息又是存在数据库当中的,每
次查询数据库就是一次 IO 操作;要想提高系统的性能,尽量减少 IO 的操作,
特别是磁盘 IO 的操作;使用缓存可以有效的避免这种情况;所以在架构设计过
程中,涉及到查询数据库的时候,应该考虑一下是不是考虑使用缓存技术来提
高系统的性能,并且降低数据库的负载。
28.请说说冒泡,选择,插入,快速排序
需要掌握这几个排序算法
思考下面问题:
1. Python 中如何使用多核.
2. 请详细描述你对 python 中的多线程的理解,什么情况下使用多线程.
3. 谈谈你对面向对象思想的理解, 为什么要使用面向对象.
4. 谈谈你对分布式的理解
5. 使用进程池和线程池的好处
6. 谈谈并发和并行的区别, 以及什么情况下使用
7. 请说说生成器的作用, 什么情况下使用?
8. 请谈谈你对 Python 闭包的理解
9. Python 中__new__()和__init()__的区别
网友评论