python面试题

1, __new__和__init__的区别
①__new__负责进行对象的创建,__init__负责进行对象的初始化
②__new__是在实例创建之前被调用,用于创建实例,然后返回该实例对象,是个静态方法,__init__是当实例对象创建完成之后被调用,用于初始化一个类实例,是个实例方法
③__new__至少有一个参数cls,必须要有返回值,返回的是实例化出来的实例,__init__在__new__基础上完成一些其他初始化的动作,__init__不需要有返回值

2,面向对象?
简称oop,把对象当做一个程序的基本单元,一个对象包含数据和操作数据的函数,提高了编程的效率,使其编程的重用性增高.
三大特点:
封装:把需要重用的函数或功能封装起来,方便其他程序直接调用,
继承 :子类继承父类,子类和父类拥有相同的方法和属性,子类会覆盖父类的方法和属性
多态:提高函数的健壮性和可扩展性,父类声明指向子类实现
多态的实现方式:
①对象多态: 在继承体系中,定义时的类型和运行时的类型不一样,此时构成多态
②类多态 : 只通过@classmethod形式多态构成的构造对象,而不是使用python默认的__init__构造器

3,如何提高Python的运行效率?
①使用生成器,节省大量内存
②针对循环优化,避免过多重复代码的执行
③多个if else条件判断,可以把最有可能发生的条件放最前面写,减少程序判断次数,提高效率

4,描述数据,链表,队列,堆栈的区别?
答:数组和链表是数据存储方式的概念,数组在连续的自然空间中存储,链表在非连续的自然空间中存储
队列和堆栈是描述数据存储方式的概念,
队列是先进先出,堆栈是后进先出,堆栈和队列可以用数组表示,也可以用链表表示,
堆和栈
内存:
栈:内存小,速度快,有序,简单的数据类型放到栈里
堆:内存大,速度慢,无序,复杂的数据类型放到堆里

5,*args和**kw区别?
*args和**kw属于不定长参数
*args返回值为元组类型,**kw返回值为字典类型

6,=和==的区别?
=:表示赋值.将某一数值赋值 给变量
==:表示判断是否相等,返回True或者False,相等True,不相等False

7,TCP/UDP/HTTP/HTTPS的区别?
TCP协议:是一种面向连接,可靠的,基于字节流的传输层协议,在正式通信前必须和对方建立连接,一个tcp必须经过三次对话才能建立连接,在经历4次对话结束(即三握四挥),传输可靠,速度慢,应用,传输大量数据,对可靠性要求高

UDP协议:用于www浏览的协议,特点是客户端发送的请求都需要服务器回送响应,在请求结束后会主动释放连接,从建立连接到关闭连接的过程成为”一次连接” 注: 1)在http1.0中客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后就自动释放连接 2)在http1.1中,则可以在一次连接中处理多次请求,并可重叠进行,不需要等一个请求结束后再发下一个请求

HTTP/HTTPS协议 HTTP协议:超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种 发布和接收HTML页面的方法。
HTTPS协议: HTTPS是一种通过计算机网络进行安全通信的传输协议,经由HTTP进行通信,利用SSL/TLS建立全信道,加密数据包。HTTPS使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性。
HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好。

8, http1.0与2.0,3.0的区别
http1.0存在连接无法复用问题,导致每发送一次请求都需要进行三次握手的过程,重新建立连接,效率太低,存在堵塞问题 ,http1.0是下一次请求的发送必须等到上一个请求返回后才会进行,如果上一个请求没有返回,name后面的请求就会全部堵塞,最后就是安全问题,http1.0所传输的内容都是明文的,无法保证数据的安全性.
http2.0比较专注性能,它采用二进制格式传输数据,http2.0也采用了多路复用的技术,他可以只通过一个TCP连接传输所有的请求数据,还有就是采用了头部压缩技术,这也解决了http1.0的header里携带的内容过大的问题,在一定程度上减轻了传输的成本,不过它也存在一定的问题,如果在传输的过程中存在丢包的情况的话,那么整个tcp就得重新传输,后面资源就会被堵塞.
http3.0放弃了tcp协议,改用了QUIC协议,此协议基于传输层UDP协议,UDP协议无需三次连接四次挥手,所以传输速率更高,如果出现丢包,只需要重发丢掉的包就可以.

9, next()和iter()的区别?
我们一般通过iter()函数获取可迭代对象的迭代器,通过对获取到的迭代器不断的通过next函数 进行获取下一条数据,iter()函数 实际上就是调用了可迭代对象的__iter__方法

10, 斐波那契数列

1
2
3
4
5
items = int(input("请输入斐波那契数列的个数:"))
fibs = [0,1]
for i in range(item - 1):
fibs.append(fibs[-2] + fibs[-1])
print("斐波那契数列为:",fibsp[1:])

11,冒泡排序

1
2
3
4
5
6
7
8
9
10
11
12
def bubblesort(list):
for i in range(len(lsit)):
for j in range(len(list)-i-1):
if list[j]>list[j+1]:
list[j],list[j+1] = list[j+1],list[j]
return list

if __name__ == '__main__':
#用户输入
str = input("请输入数字(用逗号隔开)")
list = [int(i) for i in str.split(',')]
print(bubblesort(list))

12, 类方法,静态方法,实例方法的区别
实例方法主要用于在类中封装一个额外的功能
第一个参数必须是self,一般情况下只能用实例化对象调用,不能用类调用,如果要用类调用,需要将实例化对象传递给self.
静态方法,主要用于在类中封装一个额外的功能,创建时用@staticmethod装饰器装饰,声明为静态函数,可以用类调用也可以用实例化对象调用
类方法主要是将类作为参数传递,相当于将类当成了对象,可以调用该类中的所有方法,创建时用@classmethod装饰器装饰,声明为类函数,第一个参数必须是cls,可以用类调用也可以用实例化对象调用.

代码展示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A(object):
#构造函数
def __init__(self,title1):
self.title = title1
print(self.title)
#实例函数
def foo(self,title2):
print(title2)
#静态函数
@staticmethod
def static_foo():
print("静态方法")
#类方法
@classmethod
def cls_foo(cls):
cls.foo(a,'类函数调用实例函数')
print('类方法')

13, collections库中的counter统计元素个数,

14,列表合并
a.extend(b)

15,字典合并
dic1.update(dic2)
删除 字典
del dic[‘sex’]
del:按索引删除元素
remove:默认删除第一个元素
pop:默认删除最后一个元素或者根据索引值删除索引

16,set集合去重的原理
set集合去重主要是通过函数__hash__和__eq__结合实现的
①当两个变量的哈希值不相同时,就认为两个变量时不相同的
②当两个变量哈希值一样时,调用__eq__方法,当返回值为True时认为两个变量时同一个,应该去除一个,返回FALSE时,不去重

17,分别从前端,后端,数据库阐述web项目的性能优化
前端优化:
①,减少http请求,例如制作精灵图
②,html和CSS放在页面上部,javascript放在页面下部

后端优化:
①,缓存存储读写次数高,变化少的数据,
②,异步方式,如果有耗时操作,可采用异步,如celery
③,代码优化,避免循环和判断次数太多,如果多个if else判断,优先判断最有可能发生的情况

数据库优化:
①,如有条件,数据可以存放于redis,读取速度快,
②,建立索引,外键等

18,列表切片属于浅拷贝

19, 深拷贝浅拷贝
深拷贝: 外围和内部元素都拷贝了对象本身,而不是引用,也就是说把对象复制一遍,对象中引用的其他对象也复制.
浅拷贝: 拷贝了最外围对象本身, 内部元素只拷贝了一个引用, 也就是说把对象复制一遍,对象中引用的其他对象不复制.

20, Django 、Flask、Tornado的对比
1.Django走的是大而全的方向,开发效率高。它的MTV框架,自带的ORM,admin后台管理,自带的sqlite数据库和开发测试用的服务器 给开发者提高了超高的开发效率
2.Flask是轻量级的框架,自由,灵活,可扩展性很强,核心基于Werkzeug WSGI工具和jinja2模板引擎
3.Tornado走的是少而精的方向,性能优越。它最出名的是异步非阻塞的设计方式
Tornado的两大核心模块:
1.iostraem:对非阻塞式的socket进行简单的封装
2.ioloop:对I/O多路复用的封装,它实现了一个单例

21, python垃圾回收机制
在python内部, 当一个对象的引用计数是0时, 它将被垃圾回收机制处理掉
当两个对象a和b相互引用时的情况,del语句可以减少a和b的引用计数,并销毁用于底层对象的名称,需要注意的是,并不是每一个对象都包含一个对其他对象的应用,所以这种情况下引用计数不会归0, 对象也不会被销毁,这就是可能会导致内存泄露,所以为了解决这个问题,解释器会定期执行一个循环检测器,搜素不可访问对象的循环并进行删除.

22, 线程与进程,协程
进程: 是程序执行的一次过程,是临时的,有生命周期的, 任何进程都可以同其他进程一起并发执行,是系统进行资源分配和调度的一个独立单位,由程序,数据和进程控制块三部分组成
进程池:当存在多个进程时,为避免资源损耗,创建适当的进程放入进程池,等待待处理的事件,当处理完所有事件之后,进程退出
线程: 线程是程序执行中一个单一的顺序控制流程,是程序执行的最小单元,一个进程可以有一个或多个线程,

死锁: 在线程间共享多个资源时,两个线程分别占用资源并且同时等待对方的资源,就会造成死锁,
协程: 执行函数A时可以随时中断执行函数B,然后中断函数B继续执行函数A,协程是一个线程在执行.

GIL锁:

全局解释器锁,同一进程加入有多个线程运行,一个线程在运行python程序时会霸占python解释器,也就增加了一把锁,使该进程中的其他线程无法运行,等该线程运行完成后其他线程才能运行,

23, 可变数据类型,不可变数据类型(为什么不可变,为什么可变)
可变: 列表,字典,
原因: 如果对对象进行了添加,修改等操作之后, 只是改变了变量的值,而不会新建一个对象, 变量引用的对象地址也不会发生变化,不过对于相同值的对象,即每个对象都有自己的地址,
不可变: 整型,字符串,布尔型,元组,
原因: 如果变量值发生了变化,相当于新建一个对象,而对于相同值的对象,在内存中只有一个地址,

24, 装饰器,闭包,迭代器,生成器
闭包: 外函数包含内函数, 对函数功能进行扩展,一般在装饰器下写闭包
装饰器: 为已经存在的对象添加额外的功能,在不改变原代码的情况下,扩展额外功能.(在什么情况下使用)
eg: 定义验证登录状态的装饰器
判断用户是否登录,如果登录,执行视图函数,如果未登录,返回未登录信息,然后在退出以及需要验证登录的模块调用装饰器
迭代器: for循环遍历取值的过程
生成器: yield关键字来返回值的函数

生成器(generator)的定义与普通函数类似,生成器使用yield关键字生成值。
如果一个函数包含yield关键字,那么该函数将自动成为一个生成器。

1
2
3
4
5
6
7
装饰器
def funA(fn):
pass
@funA
def fun():
print('a')
fun()

25, celery
主要是用于处理耗时任务,包含的三个模块
1, broker: 存储生产者发出的各种任务 (将任务添加到broker),存储执行结果,

 2. worker: 实时监控消息队列,如果有任务就获取任务并执行它 (worker服务)
 3. task: 定义任务函数 (任务函数),将任务添加到broker,判断任务是否执行完成.

26, Python如何处理高并发?
1.HTML页面静态化
2.图片服务器分离(可以用fastdfs轻量级的分布式文件存储系统)
3.使用缓存(用redis)
4.数据库集群、读写分离。减轻数据库服务器的读写压力。
5.使用负载均衡的方法(配置nigix服务器,用nginx来配置负载均衡,只需要设置 如下代码,即可实现简单的负载均衡)

应用场景

27, python的单例模式和工厂模式
单例模式:对__new__方式进行重写,确保一个类只有一个实例,并且提供一个访问该实例的全局访问点,
单例模式只生成一个实例对象,减少对系统资源的开销,当一个对象产生比较多的资源,如读取配置文件,产生其他依赖对象时,可以产生一个”单例对象”,然后永久驻留内存中,从而极大的降低开销.
工厂模式:实现了创建者和调用者的分离,使用专门的工厂类将选择实现类,创建对象进行统一的管理和控制.

28, python的异常类型
① ZeroDivisionError 除(或取模)零(所有数据类型)
② IndexError #序列中没有此索引
③ KeyError #映射中没有这个键
④ NameError #未声明/初始化对象 (没有属性)
⑤ SyntaxError #python语法错误
⑥ ValueError #传入无效的参数

29, json和字典的相互转换
json转字典: json.loads()
字典转json: json.jumps

30,finally关键字的作用
try:
正确语句
except:
错误信息提示
finally:
最后执行的模块

31, numpy, pandas,
np: 数组处理,矩阵运算
pd: 对csv/txt文件进行读取写入操作, 对json, 数据库, excel进行读取写操作

32,当后端任务执行完成后如何通知前端
1,前端定时发送请求询问后端有无消息,
2.django:
channels: 依赖于redis, twisted
dwebsocket:
3.在celery的tasks.py之中,当后端完成数据库读写后,往当前request所在的群组之中发送消息,随后channels会调用chat_message函数,通过self.send()方法将消息发送给前端

33, 正则表达式:
re.search(),res.match()匹配一次
match和search的区别
match()只会检测re是不是在string的开始位置匹配
search()会扫描整个string查找匹配
match()只有在0位置匹配成功的话才有返回, 如果不是开始位置匹配成功的话,match就返回none.
re.findall(): 匹配所有
re.sub()替换
re.split()分割
. 任意字符

  • 零个或多个
    ? 匹配零个或一个由前面的正则表达式定义的片段,
    贪婪模式和非贪婪模式
    在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪模式
    匹配到结果就好,少的匹配字符,就是非贪婪模式

34, Python中的self是什么?
self是类的实例或对象。在Python中,self包含在第一个参数中。但是,Java中的情况并非如此,它是可选的。它有助于区分具有局部变量的类的方法和属性。init方法中的self变量引用新创建的对象,而在其他方法中,它引用其方法被调用的对象。

35, Python数组和列表有什么区别?
python本身并没有数组类型,但Numpy库中有数组类型。
Python中的数组和列表具有相同的存储数据方式。
数组里面元素的数据类型必须是相同的,而列表可以包含任何数据类型元素。

36, classmethod, staticmethod,property

classmethod,staticmethod,property都是装饰器, 他们都作用在类的方法上。
classmethod:使得被装饰的方法成为一个类方法既不需要实例化类就可以直接调用的方法,第一个参数为cls。
staticmethod: 使得被装饰的方法成为一个静态函数既与普通的函数无区别。
property: 将一个方法变成一个属性来使用。

37, python如何进行内存管理

Python内存由Python的私有headspace管理。
所有的Python对象和数据结构都位于一个私有堆中。私用堆的分配由Python内存管理器负责。
Python还内置了一个的垃圾收集器,可以回收未使用的内存并释放内存,使其可用于headspace。

38, python2和python3的区别

①. 整数,python2中区分整型int和长整型long,python3不区分

②.python3中 True和False都是关键字,python2里面不是

③.python2中的’/‘整数相除得到的是整数,python3中的’/‘相除获得的是真除.

④.python2中print打印不一定要求函数形式使用,python3的print是强制函数

⑤. python2中的xrange相当于python3中的range,python3中没有xrange.

⑥.python2中的input默认是int型,python3中的input默认是str型

39,python常见库

sys、math、random、data time、JSON。

40, Python中append,insert和extend的区别?
append:在列表末尾添加新元素。
insert:在列表的特定位置添加元素。
extend:通过添加新列表来扩展列表。

41, break、continue、pass是什么?
break:在满足条件时,它将导致程序退出循环。
continue:将返回到循环的开头,它使程序在当前循环迭代中的跳过所有剩余语句。
pass:使程序传递所有剩余语句而不执行。

42, 如何使用索引来反转Python中的字符串

string[::-1]

43, 什么是负指数,功能是什么?
Python中的序列是索引的,它由正数和负数组成。积极的数字使用’0’作为第一个索引,’1’作为第二个索引,进程继续使用。
负数的索引从’-1’开始,表示序列中的最后一个索引,’ - 2’作为倒数第二个索引,序列像正数一样前进。
负索引用于从字符串中删除任何换行符,并允许该字符串除了作为S [: - 1]给出的最后一个字符。负索引还用于显示索引以正确的顺序表示字符串。

43、什么是Python包?
Python包是包含多个模块的命名空间。

44, capitalize()函数可以将字符串的第一个字母大写

45, range返回一个Python列表对象,x range返回一个xrange对象

46, python内存池机制

当创建大量消耗小内存的对象时,频繁调用new/malloc会导致大量的内存碎片,致使效率降低。内存池的概念就是预先在内存中申请一定数量的,大小相等的内存块留作备用,当有新的内存需求时,就先从内存池中分配内存给这个需求,不够了之后再申请新的内存。这样做最显著的优势就是能够减少内存碎片,提升效率。

-------------本文结束感谢您的阅读-------------