python面试题

1. 迭代器和生成器的区别

迭代器:它是一个带状态的对象,任何实现了iter和next()。他能在你调用next()方法的时候返回容器中的下一个值。好处是不会向列表一样直接全部读取到内存上,而是用的时候返回一个值
生成器:生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写iter()和next()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立)

2. *args and **kwargs的作用

*args是函数用来接收不定长参数的, 将参数打包成tuple给函数调用.
**kwargs 把关键字参数打包成dict给函数调用.
在不确定函数传参个数的时候,可以使用不定长参数作为形参

3. 装饰器的作用

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象

4. __new__和__init__的区别

new 方法负责创建一个实例对象,init 方法负责将该实例对象进行初始化
_new_作用于_init_之前。前者可以决定是否调用后者,或者说可以决定调用哪个类的_init_方法
new 方法若没有正确返回当前类cls的实例,那当前类的init是不会被调用的

5. 什么是单例模式

要想让一个类只能构建一个对象,也就是只让__new__方法执行一次.
应用场景: 播放器等等

6. Python中的作用域

遵循LEGB原则,
Python变量访问时有个LEGB原则,也就是说,变量访问时搜索顺序为Local ==> Enclosing ==> Global ==> Builtin
局部- > 闭包 - > 全局 -> 內建

7. 讲下对 GIL线程全局锁的理解

线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.对于io密集型任务,python的多线程起到作用,但对于cpu密集型任务,python的多线程几乎占不到任何优势,还有可能因为争夺资源而变慢。
解决方案:
1、python是胶水语言可以嵌入c语言来执行。
2、可以采用多进程

8. 线程进程协程的区别

  • 线程:线程是属于进程的,一个进程可以开辟多条线程,占用资源小,同一个进程多个线程之间的资源是共享的,多个线程可以直接对它们所在进程的内存数据进行读写并在线程间进行交换。
    使用场景:一般在处理io密集型(上传,下载,操作文件,请求网络)操作时使用
    缺点:如果多个线程同时对同一个全局变量操作,会出现资源竞争问题,从而数据结果会不正确。在cpython 线程全局锁的存在线程不能充分发挥cpu的性能
  • 进程:是系统进行资源分配和调度的基本单位:一个进程可以开辟多条线程协程,进程之间资源是不会共享的
    使用场景:一般在计算密集型操作进程可以充分发挥cpu的性能
    缺点:消耗资源大
  • 协程:协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元
    其原理是当一个协程遇到IO(指的是input 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的协程,等到IO操作完成,再在适当的时候切换回来继续执行。
    由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO

9. lambda函数

lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的匿名函数。
好处
1、lambda函数比较轻便,即用即扔,很适合需要完成某一项简单功能,但是这个简单的功能只在此一处使用,连名字都很随意的情况下;
2、lambda是匿名函数,一般用来给filter,map,reduce这样的函数式编程服务;
3、作为回调函数,可以传递给某些应用,比如消息处理等。

10. 引用和copy(),deepcopy()的区别

赋值:直接赋值,传递对象的引用而已,原始列表改变,被赋值的b也会做相同的改变
Copy : 新建一块空间拷贝子对象引用。原始对象改变本身不会改变,原始对象子对象改变本身的子对象也会改变
深拷贝:拷贝对象包含子对象,所以原始对象的改变不会造成深拷贝里任何子元素的改变

11. Python垃圾回收机制

引用计数
是最直观,最简单的垃圾回收技术。系统根据对象的引用计数判断该对象是否被引用。如:每当有一处引用,引用计数+1.每当减少一处引用,引用计数-1,当引用计数为0的时候,自动回收该对象。
Bug是如果出现循环引用的话,引用计数机制就不再起有效的作用了
标记清除
如果两个对象的引用计数都为1,但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被回收的,也就是说,它们的引用计数虽然表现为非0,但实际上有效的引用计数为0。所以先将循环引用摘掉,就会得出这两个对象的有效计数。
分代回收
从前面“标记-清除”这样的垃圾收集机制来看,这种垃圾收集机制所带来的额外操作实际上与系统中总的内存块的数量是相关的,当需要回收的内存块越多时,垃圾检测带来的额外操作就越多,而垃圾回收带来的额外操作就越少;反之,当需回收的内存块越少时,垃圾检测就将比垃圾回收带来更少的额外操作。

12. Python2和3的区别

1.Python3 对 Unicode 字符的原生支持。
Python2 中使用 ASCII 码作为默认编码方式导致 string 有两种类型 str 和 unicode,Python3 只支持 unicode 的 string。Python2 和 Python3 字节和字符对应关系为:
2.Python3 采用的是绝对路径的方式进行 import。
Python2 中相对路径的 import 会导致标准库导入变得困难(想象一下,同一目录下有 file.py,如何同时导入这个文件和标准库 file)。Python3 中这一点将被修改,如果还需要导入同一目录的文件必须使用绝对路径,否则只能使用相关导入的方式来进行导入。
3.Python2 中存在老式类和新式类的区别,Python3 统一采用新式类。新式类声明要求继承object,必须用新式类应用多重继承。
4.Python3 使用更加严格的缩进。Python2 的缩进机制中,1 个 tab 和 8 个 space 是等价的,所以在缩进中可以同时允许 tab 和 space 在代码中共存。这种等价机制会导致部分 IDE 使用存在问题。
Python3 中 1 个 tab 只能找另外一个 tab 替代,因此 tab 和 space 共存会导致报错:TabError: inconsistent use of tabs and spaces in indentation.

13. 数据库事务的理解

  • 原子性(Atomicity)原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
  • 一致性(Consistency) - 一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
  • 隔离性(Isolation) - 隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。
  • 持久性(Durability) - 持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。   例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。 - 以上介绍完事务的四大特性(简称ACID),现在重点来说明下事务的隔离性,当多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性,在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种问题:

14. 谈下mysql,MongoDB,redis

MySQL 数据库:开源免费的关系型数据库,需要实现创建数据库、数据表和表的字段,表与表之间可以进行关联(一对多、多对多),支持事务,是持久化存储, 主要的数据库引擎是Innodb, Myisam。
Mongodb 数据库:是非关系型数据库,数据库的三元素是,数据库、集合、文档,可以进行持久化存储,也可作为内存数据库,存储数据不需要事先设定格式,数据以键值对的形式存储。
redis 数据库:非关系型数据库,内存型数据库,使用前可以不用设置格式,以键值对的方式保存,文件格式相对自由,主要用与缓存数据库,也可以进行持久化存储。

15. 三次握手,四次挥手

三次握手过程:
1 首先客户端向服务端发送一个带有 SYN 标志,以及随机生成的序号 100(0 字节)的报文
2 服务端收到报文后返回一个报文(SYN200(0 字节),ACk1001(字节+1))给客户端
3 客户端再次发送带有 ACk 标志 201(字节+)序号的报文给服务端
至此三次握手过程结束,客户端开始向服务端发送数据
补充:SYN:请求询问,ACk:回复。
由于 TCP 连接是可以双向通信的(全双工),因此每个方向都必须单独进行关闭(这句话才是精辟,后面四个挥手过程都是其具体实现的语言描述)
四次挥手过程,客户端和服务端都可以先开始断开连接
1 客户端发送带有 fin 标识的报文给服务端,请求通信关闭
2 服务端收到信息后,回复 ACK 答应关闭客户端通信(连接)请求
3 服务端发送带有 fin 标识的报文给客户端,也请求关闭通信
4 客户端回应 ack 给服务端,答应关闭服务端的通信(连接)请求

16. post,get的区别

GET 请求,请求的数据会附加在 URL 之后,以?分割 URL 和传输数据,多个参数用&连接。URL 的编码格式采用的是 ASCII 编码,而不是 uniclde,即是说所有的非 ASCII 字符都要编码之后再传输。
POST 请求:POST 请求会把请求的数据放置在 HTTP 请求包的包体中。上面的 item=bandsaw 就是实际的传输数据。 因此,GET 请求的数据会暴露在地址栏中,而 POST 请求则不会传输数据的大小:
在 HTTP 规范中,没有对 URL 的长度和传输的数据大小进行限制。但是在实际开发过程中,对于 GET,特定的浏览器和服务器对 URL 的长度有限制。因此,在使用 GET 请求时,传输数据会受到 URL 长度的限制。
对于 POST,由于不是 URL 传值,理论上是不会受限制的,但是实际上各个服务器会规定对 POST提交数据大小进行限制,Apache、IIS 都有各自的配置。
安全性:
POST 的安全性比 GET 的高。这里的安全是指真正的安全,而不同于上面 GET 提到的安全方法中的安全,上面提到的安全仅仅是不修改服务器的数据。比如,在进行登录操作,通过 GET 请求, 用户名和密码都会暴露再 URL 上,因为登录页面有可能被浏览器缓存以及其他人查看浏览器的
历史记录的原因,此时的用户名和密码就很容易被他人拿到了。除此之外,GET 请求提交的数据还可能会造成 Cross-site request frogery 攻击。

17. 索引有什么用,大致原理是什么?设计索引有什么注意点?

索引:数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。
原理:索引的实现通常使用 B_TREE,B_TREE 索引加速了数据访问,因为存储引擎不会再去扫描整张表得到需要的数据;相反,它从根节点开始,根节点保存了子节点的指针,存储引擎会根据指针快速寻找数据。
注意点:数据量少就不用建立索引了,一张表索引字段不要超过4个。
应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描
应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,

18. mysql的一些查询以及优化

1、如果不需要事务处理,使用默认存储引擎 MyISAM 是比较明智的
2、禁止使用外键
3、分表分库,主从。
4、对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
5、Update 语句,如果只更改 1、2 个字段,不要 Update 全部字段,否则频繁调用会引起明显的性能消耗

19. 常见排序的实现原理及代码实现,各种排序的时间复杂度

# 冒泡排序
nums = [1, 8, 7, 6, 4, 3, 2]
for i in range(len(nums)):
    for j in range(i+1, len(nums)):
        if nums[i] > nums[j]:
            nums[i], nums[j] = nums[j], nums[i]

# 快速排序
def quicksort(array):
    less = []
    greater = []
    if len(array) <= 1:
        return array
    pivot = array.pop()
    for x in array:
        if x <= pivot:
            less.append(x)
        else:
            greater.append(x)
    return quicksort(less)+[pivot]+quicksort(greater)


import random
nums = [random.randint(1, 100) for _ in range(100)]
print(nums)
print(quicksort(nums))

20. 介绍下你最近做的一个项目,以及你负责那些模块,以及业务逻辑是如何处理的

1、使用django-cors-headers拓展解决跨域问题
2、登录采用djangorestframework-jwt拓展做认证机制
3、忘记密码每一步使用itsdangerous生成accesstoken保证接口安全,
4、使用页面静态化技术提高服务器性能
5、使用celery异步执行耗时操作如:发送短信验证码、邮件,以及定时更新商品静态化页面
6、搜索基于docker采用搜索引擎Elasticsearch,
7、购物车模仿京东在用户未登录情况下商品数据存在cookie,登录存在redis。登录是合并cookie数据到redis
8、高并发下购买商品使用乐观锁机制保证数据稳定。
9、文件存储采用七牛云(了解搭建FastDFS文件系统)
10、项目采用表关系采用逻辑外键。某些数据采用缓存加载,mysql主从配置优化性能。

21. 对于需要登录的网站是怎么解决的

使用selenium 登录网址并获取cookie

22. 你们公司的去重是怎么做的

文件去重采用第三方服务七牛云

23. 高匿名代理ip访问网站和普通匿名ip以及透明ip访问网站有什么区别

1、透明代理(Transparent Proxy)
• REMOTE_ADDR = Proxy IP
• HTTP_VIA = Proxy IP
• HTTP_X_FORWARDED_FOR = Your IP
透明代理虽然可以直接“隐藏”你的IP地址,但是还是可以从HTTP_X_FORWARDED_FOR来查到你是谁。
2、匿名代理(Anonymous Proxy)
• REMOTE_ADDR = proxy IP
• HTTP_VIA = proxy IP
• HTTP_X_FORWARDED_FOR = proxy IP
匿名代理比透明代理进步了一点:别人只能知道你用了代理,无法知道你是谁。
还有一种比纯匿名代理更先进一点的:混淆代理,见下节。
3、混淆代理(Distorting Proxies)
• REMOTE_ADDR = proxy IP
• HTTP_VIA = proxy IP
• HTTP_X_FORWARDED_FOR = Random IP address
如上,与匿名代理相同,如果使用了混淆代理,别人还是能知道你在用代理,但是会得到一个假的IP地址,伪装的更逼真:-)
4、高匿代理(Elite proxy或High Anonymity Proxy)
• REMOTE_ADDR = Proxy IP
• HTTP_VIA = not determined
• HTTP_X_FORWARDED_FOR = not determined

24. 谈一下你对orm的理解

ORM简称对象关系映射,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
ORM技术特点:
1.提高了开发效率。由于ORM可以自动对对象与数据库中的Table进行字段与属性的映射,
2.ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。
缺点:在对对象做持久化时,ORM一般会持久化所有的属性,有时,这是不希望的。

##25. 常见的反爬手段以及解决方法

1通过headers中的User-Agent字段来反爬
2 通过referer字段或者是其他字段来反爬
3 通过cookie来反爬
4 通过js来反爬
5通过验证码来反爬
6 通过ip地址来反爬
7 通过css来反爬

26. Ajax

AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
Ajax是异步执行的
Ajax 发送异步请求来获取数据然后更新页面上的内容

27. RESTful架构

REST是一种设计风格
RESTful架构就是:
1、每一个URL代表一种资源;
2、客户端和服务器之间,传递这种资源的某种表现层;
3、客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。
状态转换, 就是客户端和服务器互动的一个过程,在这个过程中, 势必涉及到数据和状态的变化, 这种变化叫做状态转换。
在REST风格里每一种请求方式对应的一种操作

28. XSRF和XSS

XSS:跨站脚本是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端脚本语言。
在一个论坛发帖中发布一段恶意的JavaScript代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS!
CSRF:跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
CSRF:用户在登录A网站时在没退出的情况下访问恶意网站B,B网站里伪造一条链接是请求访问A网站的某个接口,这个时候用户点击这条链接会自动带上cookie访问,A网站会以为是用户的操作。
如何防止CSRF
服务端端开启 csrf认证之后,
客户端发送get请求 要form表单时,在里面加上csrf_token一个随机字符串
客户端收到这个 带随机字符串的 form表单之后
客户端在向服务端 发post请求(不仅要有cokie还检查这个from表单是不是携带 csrf_token)
(不要以为有了cokie就可以随意发送 post请求了!)

29. HTTP和HTTPS的区别

HTTP: 超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息。HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此HTTP协议不适合传输一些敏感信息,比如信用卡号、密码等。
HTTPS: 安全套接字层超文本传输协议HTTPS。为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
HTTP 有点传输速度快
HTTPS传输速度没HTTP快,但是安全

30. Cookie和Session的区别

1、cookie 数据存放在客户的浏览器上,session 数据放在服务器上。
2、cookie 不是很安全,别人可以分析存放在本地的 cookie 并进行 cookie 欺骗考虑到安全应当使用
session。
3、session 会在一定时间内保存在服务器上。当访问增多,会比较占用服务器的性能考虑到减轻服务器性能方面,应当使用 cookie。
4、单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie。
5、建议: 将登陆信息等重要信息存放为 SESSION 其他信息如果需要保留,可以放在 cookie 中

31 七层模型

1、应用层
2、表示层
3、会话层
4、传输层
5、网络层
6、链路层
7、物理层
TCP/IP 应用层+表示层+会话层

map、filter、reduce

  • map :第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表
  • filter:函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
    该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
  • reduce: 函数会对参数序列中元素进行累积。
    函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。

Django

ORM

ORM的概念

ORM是通过使用描述对象和数据库之间映射的元数据
ORM将程序中的对象自动持久化到关系数据库中
ORM在业务逻辑层到数据库层中充当桥梁作用
ORM的劣势: 在一定程度上牺牲了程序的执行效率
ORM的优势:解决了对象与关系的映射。提高的开发效率,和健壮程度。

信号机制

  • 在项目中的__init__方法里
    django.db.models.signals.pre_save 在某个Model保存之前调用
    django.db.models.signals.post_save 在某个Model保存之后调用
    django.db.models.signals.pre_delete 在某个Model删除之前调用
    django.db.models.signals.post_delete 在某个Model删除之后调用
    django.core.signals.request_started 在建立Http请求时发送
    django.core.signals.request_finished 在关闭Http请求时发送
import django
django.setup()

from django.db.models.signals import pre_save
from django.dispatch import receiver
from users.models import User


@receiver(pre_save, sender=User)
def send_user(sender, **kwargs):
    print(sender)
    print("保存了一个用户")

F对象

模型两个属性怎么比较

Q对象

主要 “或“ 条件查询 BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))

查询集 QuerySet

all():返回所有数据。
filter():返回满足条件的数据。
exclude():返回满足条件之外的数据。
order_by():对结果进行排序。

两大特性

###1)惰性执行
创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用

2)缓存

使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。


MyISAM、InnoDB区别

MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。
MyISAM表不支持外键,InnoDB支持
MyISAM锁的粒度是表级,而InnoDB支持行级锁定。
MyISAM支持全文类型索引,而InnoDB不支持全文索引。(mysql 5.6后innodb支持全文索引)

数据库优化手段

1、引擎方面,如果是只查询使用MyISAM,
2、查询大量数据要建立索引,索引数量不要超过4个, 禁止在平凡更改的字段简历索引
3、禁止使用物理外键
4、准从三范式
5、主从配置(读写分离),
6、对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
7、Update 语句,如果只更改 1、2 个字段,不要 Update 全部字段,否则频繁调用会引起明显的性能消耗
8、大数据表禁止使用关联查询。

数据库存储过程

存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值