Python-常见面试题汇总参考:Python-面向对象编程总结

目录html

基础与特性前端

列举布尔值为False的常见值?python

Python递归的最大层数?web

print([i%2 for i in range(10)])和print((i%2 for i in range(10)))的结果?sql

简述解释型语言和编译型语言?数据库

解释器种类及特色django

字符串格式化有哪几种?编程

简述字符串驻留机制?json

什么是反射,举个例子flask

Python自省

Python做用域

函数及函数式编程

函数调用时参数传递方式?

什么是闭包?

什么是lambda函数?

装饰器

装饰器的做用和功能?

迭代器、生成器

迭代器和生成器的区别是什么?

拷贝

深拷贝和浅拷贝有什么区别?

线程、进程与协程

如何在Python中实现多线程?

协程

面向对象

Python的元类?

静态方法,类方法

类变量和实例变量

Python中单下划线和双下划线

重载

__new__和__init__的区别

文件

read,readline和readlines

内存管理

Python垃圾回收机制?

Python是如何进行内存管理的?

WEB

什么是wsgi,uwsgi,uWSGI?

Django、Flask的对比?

Django

django请求的生命周期?

列举django的内置组件?

简述什么是FBV和CBV?

django中csrf防护的实现机制

Django自己提供了runserver,为何不能用来部署?

跨域问题如何解决?

参考


基础与特性

列举布尔值为False的常见值?

0,[],(),{},'',Flase,None

Python递归的最大层数?

998

def fun(num):
    if num == 0:
        return 0
    else:
        return fun(num - 1)


if __name__ == '__main__':
    print(fun(998))

结果

RecursionError: maximum recursion depth exceeded in comparison

print([i%2 for i in range(10)])和print((i%2 for i in range(10)))的结果?

>>> print([i%2 for i in range(10)])
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
>>> print((i%2 for i in range(10)))
<generator object <genexpr> at 0x00000283335C7F48>

一个是列表,一个是生成器/迭代器

简述解释型语言和编译型语言?

-编译型(须要编译器,至关于用谷歌翻译):编译型语言执行速度快,不依赖语言环境运行,跨平台差,如C/C++执行速度快,调试麻烦

-解释型(须要解释器,至关于同声传译):解释型跨平台好,一份代码,处处使用,缺点是执行速度慢,依赖解释器运行,如Python、JAVA执行速度慢,调试方便

解释器种类及特色

    CPython是使用最广且被的Python解释器。
    IPython是基于CPython之上的一个交互式解释器,也就是说,IPython只是在交互方式上有所加强,可是执行Python代码的功能和CPython是彻底同样的。CPython用>>>做为提示符,而IPython用In[序号]:做为提示符。
    PyPy是另外一个Python解释器,它的目标是执行速度。PyPy采用JIT技术,对Python代码进行动态编译(注意不是解释),因此能够显著提升Python代码的执行速度。绝大部分Python代码均可以在PyPy下运行,可是PyPy和CPython有一些是不一样的,这就致使相同的Python代码在两种解释器下执行可能会有不一样的结果。若是你的代码要放到PyPy下执行,就须要了解PyPy和CPython的不一样点。
    Jython是运行在Java平台上的Python解释器,能够直接把Python代码编译成Java字节码执行。
    IronPython和Jython相似,只不过IronPython是运行在微软.Net平台上的Python解释器,能够直接把Python代码编译成.Net的字节码。

字符串格式化有哪几种?

占位符

>>> 'hello,%s' % 'world'
'hello,world'

format

>>> 'hello,{}'.format('world')
'hello,world'

f-string

>>> f'hello,{"world"}'
'hello,world'

简述字符串驻留机制?

对于短字符串,将其照值给多个不一样的对象时,内存中只有一个副本,多个对象共享该副本。长字符串不遵照驻留机制。
驻留适用范围:由数字,字符和下划线组成的python标识符以及整数[-5,256]。

>>> s1='hello_world'
>>> s2='hello_world'
>>> id(s1)
2762526059824
>>> id(s2)
2762526059824 

>>> s1='hello_world'*10000
>>> s2='hello_world'*10000
>>> id(s1)
2762523045808
>>> id(s2)
2762523155872 

什么是反射,举个例子

反射是把字符串映射到实例的变量或者实例的方法而后能够去执行调用、修改等操做。利用如下四个内置函数:

  • getattr 获取指定字符串名称的对象属性
  • setattr 为对象设置一个对象
  • hasattr 判断对象是否有对应的对象(字符串)
  • delattr 删除指定属性

例如:

>>> s2='hello_world'
>>> getattr(s2,'split')('_')
['hello', 'world']

Python自省

运行时得到对象的类型等,内置函数dir、type、isinstance等,利用了反射机制。

Python做用域

本地做用域(Local)→当前做用域被嵌入的本地做用域(Enclosing locals)→全局/模块做用域(Global)→内置做用域(Built-in)

函数及函数式编程

函数调用时参数传递方式?

函数传参是引用传递,函数外一直不变,须要区分对象是否可变。对于不可变类型,能够经过返回修改后的引用来改变它(指向其余地方)。

函数基础总结与内置函数

什么是闭包?

在一个函数内部的函数,具体来讲:

  • 必须有一个内嵌函数
  • 内嵌函数必须引用外部函数中的变量
  • 外部函数的返回值必须是内嵌函数

什么是lambda函数?

lambda函数也叫匿名函数,该函数能够包含任意数量的参数,但只能有一个执行操做的语句

装饰器

装饰器的做用和功能?

一句话:为已经存在的对象添加额外的功能

  • 引入日志
  • 函数执行时间统计
  • 执行函数栈预备处理
  • 执行函数后的清理功能
  • 权限校验
  • 缓存

迭代器、生成器

迭代器和生成器的区别是什么?

一、共同点

生成器是一种特殊的迭代器。

二、不一样点

a、语法上:

生成器是经过函数的形式中调用 yield 或()的形式建立的,自动建立了__iter__()和next()方法,显得特别简洁,也是高效的。

迭代器能够经过iter()内置函数建立。

b、用法上:

生成器在调用next()函数或for循环中,全部过程被执行,且返回值,须要的时候才返回,生成器表达式比列表生成式更节省内存

迭代器在调用next()函数或for循环中,全部值被返回,没有其余过程或动做。

拷贝

深拷贝和浅拷贝有什么区别?

在建立新实例类型时使用浅拷贝,并保留在新实例中复制的值。浅拷贝用于复制引用指针,就像复制值同样。这些引用指向原始对象,而且在类的任何成员中所作的更改也将影响它的原始副本。浅拷贝容许更快地执行程序,它取决于所使用的数据的大小。

深拷贝用于存储已复制的值。深拷贝不会将引用指针复制到对象。它引用一个对象,并存储一些其余对象指向的新对象。原始副本中所作的更改不会影响使用该对象的任何其余副本。因为为每一个被调用的对象建立了某些副本,所以深拷贝会使程序的执行速度变慢。

浅拷贝拷贝数据集合的第一层数据,深拷贝拷贝数据集合的全部层。

线程、进程与协程

如何在Python中实现多线程?

Python有一个多线程库,可是用多线程来加速代码的效果并非那么的好,

Python有一个名为Global Interpreter Lock(GIL)的结构。GIL确保每次只能执行一个“线程”。一个线程获取GIL执行相关操做,而后将GIL传递到下一个线程。

虽然看起来程序被多线程并行执行,但它们实际上只是轮流使用相同的CPU核心

全部这些GIL传递都增长了执行的开销。这意味着多线程并不能让程序运行的更快。

协程

简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户本身控制切换的时机,再也不须要陷入系统的内核态。

Python里最多见的yield就是协程的思想!

面向对象

Python的元类?

先定义metaclass,就能够建立类,最后建立实例。

因此,metaclass容许你建立类或者修改类。换句话说,你能够把类当作是metaclass建立出来的“实例”。它指示Python解释器在建立MyList时,要经过ListMetaclass.__new__()来建立。

ORM就是一个典型的例子。

静态方法,类方法

\ 实例方法 类方法 静态方法
a = A() a.foo(x) a.class_foo(x) a.static_foo(x)
A 不可用 A.class_foo(x) A.static_foo(x)

实例方法,类没法调用。类方法和静态方法类和实例均可以调用。A.class_foo(x)能够理解为class_foo(A,x),a.class_foo(x)能够理解为class_foo(a,x),a会转化为A。静态方法和类没有太大关系。

类变量和实例变量

类变量是全部实例共享的

实例变量是实例单独拥有的

Python中单下划线和双下划线

双下划线"__变量或函数__",是Python内部为了防止和用户自定义命名冲突。

双下划线"__变量或函数",解析器用_classname__foo来代替这个名字,以区别和其余类相同的命名,它没法直接像公有成员同样随便访问,经过对象名._类名__xxx这样的方式能够访问。

单下划线"_变量或函数",是指定变量私有,不能经过from module import *导入,其余地方和公有同样。

参考:Python-面向对象编程总结

重载

  1. 可变参数类型。
  2. 可变参数个数。

基本的设计原则:仅仅当两个函数除了参数类型和参数个数不一样之外,其功能是彻底相同的,此时才使用函数重载。

__new____init__的区别

  1. __new__是一个静态方法,__init__是一个实例方法
  2. __new__方法会返回一个建立的实例,而__init__什么都不返回。
  3. 只有在__new__返回一个cls的实例时后面的__init__才能被调用。
  4. 建立一个新实例时调用__new__,初始化一个实例时用__init__

利用__new__可实现单例模式

文件

read,readline和readlines

  • read 读取整个文件
  • readline 读取下一行,使用生成器方法
  • readlines 读取整个文件到一个迭代器以供咱们遍历
内存管理

Python垃圾回收机制?

垃圾回收:

Python不像C++,Java等语言同样,他们能够不用事先声明变量类型而直接对变量进行赋值。对python语言来说,对象的类型和内存都是在运行时肯定的。这也是为何咱们称python语言为动态类型的缘由(这里咱们把动态类型语言能够简单的归结为对变量内存地址的分配是在运行时自动判断变量类型并对变量进行赋值)。

引用计数:

Python采用了相似windows内核对象同样的方式来对内存进行管理。每个对象,都维护这一个对指向该对象的引用的计数。当变量被绑定在一个对象上的时候,该变量的引用计数就是1,,系统会自动维护这些标签,并定时扫描,当某标签的引用计数变为0的时候,该对象就会被回收。

标记-清除:

“标记-清除”不改动真实的引用计数,而是将集合中对象的引用计数复制一份副本,改动该对象引用的副本。对于副本作任何的改动,都不会影响到对象生命走起的维护。基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发遍历以对象为节点、以引用为边构成的图,把全部能够访问到的对象打上标记,而后清扫一遍内存空间,把全部没标记的对象释放。
分代回收:

将系统中的全部内存块根据其存活时间划分为不一样的集合,每个集合就成为一个“代”,垃圾收集的频率随着“代”的存活时间的增大而减少。也就是说,活得越长的对象,就越不多是垃圾,就应该减小对它的垃圾收集频率。那么如何来衡量这个存活时间:一般是利用几回垃圾收集动做来衡量,若是一个对象通过的垃圾收集次数越多,能够得出:该对象存活时间就越长。

举例: 当某些内存块M通过了3次垃圾收集的清洗以后还存活时,咱们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工做时,大多数状况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔至关长一段时间后才进行,这就使得垃圾收集机制须要处理的内存少了,效率天然就提升了。

Python是如何进行内存管理的?

内存池机制:

    python的内存机制成金字塔形:

    第-1,-2层主要有操做系统进行操做;

    第0层是C中的malloc,free等内存分配和释放函数进行操做;

    第1层和第2层是内存池,有python的接口函数PyMem_Malloc函数实现,当对象小于256字节时由该层直接分配内存;

    第三层是最上层,也就是咱们对python对象的直接操做;

在C中若是频繁的调用malloc与free时,是会产生性能问题的,在加上频繁的分配和释放小块的内存会产生内存碎片。

python在这里主要干的工做有:

若是请求分配的内存在1~256字节之间就使用本身的内存管理系统,不然直接使用malloc。

这里仍是会调用malloc分配内存,但每次回分配一块大小为256字节的大块内存。

经由内存池登记的内存到最后仍是会回收到内存池,并不会调用C的free释放掉,以便下次使用。对于简单的python对象,例如数值、字符串、元组(tuple不容许被更改)采用的是复制的方式(深拷贝),也就是说当讲另外一个变量B赋值给变量A时,虽然A和B的内存空间仍然相同,可是当A的值发生变化时,会从新给A分配空间,A和B的地址变得再也不相同。

WEB

什么是wsgi,uwsgi,uWSGI?

WSGI:

web服务器网关接口,是一套协议。用于接收用户请求并将请求进行初次封装,而后将请求交给web框架。

实现wsgi协议的模块:wsgiref,本质上就是编写一socket服务端,用于接收用户请求(django)

werkzeug:本质上就是编写一个socket服务端,用于接收用户请求(flask)

uwsgi:与WSGI同样是一种通讯协议,它是uWSGI服务器的独占协议,用于定义传输信息的类型。

uWSGI:是一个web服务器,实现了WSGI的协议,uWSGI协议,http协议

Django、Flask的对比?

一、 Django走的大而全的方向,开发效率高。它的MTV框架,自带的ORM,admin后台管理,自带的sqlite数据库和开发测试用的服务器,给开发者提升了超高的开发效率。 重量级web框架,功能齐全,提供一站式解决的思路,能让开发者不用在选择上花费大量时间。

自带ORM和模板引擎,支持jinja等非官方模板引擎。

自带ORM使Django和关系型数据库耦合度高,若是要使用非关系型数据库,须要使用第三方库

自带数据库管理app

成熟,稳定,开发效率高,相对于Flask,Django的总体封闭性比较好,适合作企业级网站的开发。python web框架的先驱,第三方库丰富

二、 Flask 是轻量级的框架,自由,灵活,可扩展性强,核心基于Werkzeug WSGI工具 和jinja2 模板引擎

适用于作小网站以及web服务的API,开发大型网站无压力,但架构须要本身设计

与关系型数据库的结合不弱于Django,而与非关系型数据库的结合远远优于Django

Django

django请求的生命周期?

  • 当用户在浏览器中输入url时,浏览器生成请求头和请求体发给服务端,请求头和请求体中包含浏览器的动做(action),这个动做一般为Get或者Post
  • url通过Django中的wsgi,再通过Django的中间件,最后url到路由映射表,在路由中一条一条进行匹配,一旦其中一条匹配成功就执行对应的视图函数,后面的路由就再也不继续匹配了
  • 视图函数根据客户端的请求查询相应的数据,返回给Django,而后Django把客户端想要的数据返回
  • 客户端浏览器接收到返回的数据,通过渲染后显示给用户

列举django的内置组件?

  • .Admin是对model中对应的数据表进行CRUD提供的组件
  • .model组件:负责操做数据库
  • .form组件:1.生成HTML代码 2.数据有效性校验 3校验信息返回并展现
  • .ModelForm组件:用于数据库操做,也可用于用户请求的验证

简述什么是FBV和CBV?

FBV和CBV本质是同样的,基于函数的视图叫作FBV,基于类的视图叫作CBV
在python中使用CBV的优势:

  • 提升了代码的复用性,可使用面向对象的技术,例如Mixin(多继承)
  • 能够用不一样的函数针对不一样的HTTP方法处理,而不是经过不少if判断,提升代码可读性

django中csrf防护的实现机制

  • 第一步:django第一次响应来自某个客户端的请求时,后端随机产生一个token值,把这个token保存在SESSION状态中,同时,后端把这个token放到cookie中交给前端页面
  • 第二步:下次前端须要发起请求的时候把这个token值加入到请求数据或者头信息中,一块儿传给后端;Cookies:{csrf_token:xxxxx}
  • 第三步:后端校验前端请求带过来的token和SESSION里的token是否一致。

Django自己提供了runserver,为何不能用来部署?

  • 1.runserver方法是调试 Django 时常常用到的运行方式,它使用Django自带的WSGI Server 运行,主要在测试和开发中使用,而且 runserver 开启的方式也是单进程。
  • 2.uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http 等协议。注意uwsgi是一种通讯协议,而uWSGI是实现uwsgi协议和WSGI协议的 Web 服务器。uWSGI具备超快的性能、低内存占用和多app管理等优势,而且搭配着Nginx就是一个生产环境了,可以将用户访问请求与应用 app 隔离开,实现真正的部署 。相比来说,支持的并发量更高,方便管理多进程,发挥多核的优点,提高性能

跨域问题如何解决?

  • cors:安装django-cors-headers
  • jsonp

不断更新中...