面试

1.谈一谈Python的装饰器(decorator)

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

2.简要描述Python的垃圾回收机制

引用计数:Python在内存中存储每个对象的引用计数,如果计数变成0,该对象就会消失,分配给该对象的内存就会释放出来。

标记-清除:一些容器对象,比如list、dict、tuple,instance等可能会出现引用循环,对于这些循环,垃圾回收器会定时回收这些循环(对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边)。

分代收集:Python把内存根据对象存活时间划分为三代,对象创建之后,垃圾回收器会分配它们所属的代。每个对象都会被分配一个代,而被分配更年轻的代是被优先处理的,因此越晚创建的对象越容易被回收。

2. __new__和__init__的区别

_new_ 方法负责创建一个实例对象,_init_ 方法负责将该实例对象进行初始化;​

new() 方法是在类准备将自身实例化时调用;
-new() 方法始终都是类的静态方法,即使没有被加上静态方法装饰器 ;
继承自object的新式类才有new;
new至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供;​
-new必须要有返回值,返回实例化出来的实例,这点在自己实现new时要特别注意,可以return父类new出来的实例,或直接是object的new出来的实例。

​_init_有一个参数self,就是这个_new_返回的实例,_init_在_new_的基础上可以完成一些其它初始化的动作,_init_不需要返回值;

3.说一说Python自省

help,dir([obj]),sys,type().....

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

从三个方面来说,一对象的引用计数机制,二垃圾回收机制,三内存池机制

一、对象的引用计数机制

python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。

引用计数增加的情况:

1,一个对象分配一个新名称

2,将其放入一个容器中(如列表、元组或字典)

引用计数减少的情况:

1,使用del语句对对象别名显示的销毁

2,引用超出作用域或被重新赋值

sys.getrefcount( )函数可以获得对象的当前引用计数

多数情况下,引用计数比你猜测得要大得多。对于不可变数据(如数字和字符串),解释器会在程序的不同部分共享内存,以便节约内存。

二、垃圾回收

1,当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。

2,当两个对象ab相互引用时,del语句可以减少ab的引用计数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。

三、内存池机制

Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。

1Pymalloc机制。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。

2Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的malloc

3,对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。

5.Python里面如何实现tuplelist的转换?

函数tuple(seq)可以把所有可迭代的(iterable)序列转换成一个tuple, 元素不变排序也不变。

例如,tuple([1,2,3])返回(1,2,3),tuple(abc’)返回(a’.’b',’c').如果参数已经是一个tuple的话函数不做任何拷贝而直接返回原来的对象所以在不确定对象是不是tuple的时候来调用tuple()函数也不是很耗费的。

函数list(seq)可以把所有的序列和可迭代的对象转换成一个list,元素不变排序也不变。

例如list([1,2,3])返回(1,2,3),list(’abc’)返回['a', 'b', 'c']。如果参数是一个list,她会像set[:]一样做一个拷贝

6.Python里面如何拷贝一个对象?

一般来说可以使用copy.copy()方法或者copy.deepcopy()方法几乎所有的对象都可以被拷贝

一些对象可以更容易的拷贝Dictionaries有一个copy方法:

newdict = olddict.copy()

7.用Python来进行查询和替换一个文本字符串?

可以使用sub()方法来进行查询和替换sub方法的格式为sub(replacement, string[, count=0]) replacement是被替换成的文本 string是需要被替换的文本 count是一个可选参数指最大被替换的数量

例子:

import re

p = re.compile((blue|white|red)’)

print(p.sub(colour,'blue socks and red shoes’))

print(p.sub(colour,'blue socks and red shoes’, count=1))

输出

colour socks and colour shoes

colour socks and red shoes

subn()方法执行的效果跟sub()一样不过它会返回一个二维数组包括替换后的新的字符串和总共替换的数量

例如:

import re

p = re.compile((blue|white|red)’)

print(p.subn(colour,'blue socks and red shoes’))

print(p.subn(colour,'blue socks and red shoes’, count=1))

输出

(colour socks and colour shoes’, 2)

(colour socks and red shoes’, 1)

8.Python里面match()search()的区别?

match()函数只检测RE是不是在string的开始位置匹配, search()会扫描整个string查找匹配, 也就是说match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none

9. 迭代器和生成器

迭代器:是访问集合元素的一种方式,从集合的第一个元素开始访问,直到所有元素被访问结束。其优点是不需要事先准备好整个迭代过程中的所有元素,仅在迭代到某个元素时才开始计算该元素。适合遍历比较巨大的集合。__iter__():方法返回迭代器本身,__next__():方法用于返回容器中下一个元素或数据。

生成器:带有yield的函数不再是一个普通函数,而是一个生成器。当函数被调用时,返回一个生成器对象。不像一般函数在生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行状态。

'''迭代器'''

print('for x in iter([1, 2, 3, 4, 5]):')

for x in iter([1, 2, 3, 4, 5]):

print(x)

'''生成器'''

def myyield(n):

while n>0:

print("开始生成...:")

yield n

print("完成一次...:")

n -= 1

for i in myyield(4):

print("遍历得到的值:",i)

9.闭包

闭包可以实现先将一个参数传递给一个函数,而并不立即执行,以达到延迟求值的目的。满足以下三个条件:必须有一个内嵌函数;内嵌函数必须引用外部函数中变量;外部函数返回值必须是内嵌函数。

10.什么是GIL

 Python代码的执行由python虚拟机(也叫解释器主循环,CPython版本)来控制,Python在设计之初就考虑到要在解释器的主循环中,同时只有一个线程在执行,即任意时刻,只有一个线程在解释器中运行。对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。

11.对比一下dict中items 与iteritems

dict.items()返回的是一个完整的列表,而dict.iteritems()返回的是一个生成器(迭代器)。
dict.items()返回列表list的所有列表项,形如这样的二元组list:[(key,value),(key,value),...],dict.iteritems()是generator, yield 2-tuple。相对来说,前者需要花费更多内存空间和时间,但访问某一项的时间较快(KEY)。后者花费很少的空间,通过next()不断取下一个值,但是将花费稍微多的时间来生成下一item。

12.是否遇到过python的模块间循环引用的问题,如何避免它

这是代码结构设计的问题,模块依赖和类依赖 如果老是觉得碰到循环引用,很可能是模块的分界线划错地方了。可能是把应该在一起的东西硬拆开了,可能是某些职责放错地方了,可能是应该抽象的东西没抽象 总之微观代码规范可能并不能帮到太多,重要的是更宏观的划分模块的经验技巧,推荐uml,脑图,白板等等图形化的工具先梳理清楚整个系统的总体结构和职责分工 采取办法,从设计模式上来规避这个问题,比如: 1. 使用 “__all__” 白名单开放接口 2. 尽量避免 import

13.python数据结构

list,tuple, dict, set

14.Python如何实现单例模式?其他23种设计模式python如何实现?

https://www.cnblogs.com/huchong/p/8244279.html

15.解释一下WSGI 和FastCGI 的关系?

WSGI是python的接口规范,这个规范是针对WEB服务器和python应用(框架等)的交互的。FASTCGI则是两者底层的通信协议的规范。

16.解释一下Django 和Tornado 的关系、差别

Django适合初学者或者小团队的快速开发,适合做管理类、博客类网站、或者功能十分复杂需求十分多的网站

Tornado适合高度定制,适合访问量大,异步情况多的网站

17.解释下Django使用redis缓存服务器

为了能在Django中使用redis,还需要安装redis for Django的插件。然后在Django的settings中配置了。

18. scrapy框架

1.首先Spiders(爬虫)将需要发送请求的url(requests)经ScrapyEngine(引擎)交给Scheduler(调度器)。

2.Scheduler(排序,入队)处理后,经ScrapyEngine,DownloaderMiddlewares(可选,主要有User_Agent, Proxy代理)交给Downloader。

3.Downloader向互联网发送请求,并接收下载响应(response)。将响应(response)经ScrapyEngine,SpiderMiddlewares(可选)交给Spiders。

4.Spiders处理response,提取数据并将数据经ScrapyEngine交给ItemPipeline保存(可以是本地,可以是数据库),提取url重新经ScrapyEngine交给Scheduler进行下一个循环。直到无Url请求程序停止结束。

 

19.什么是Flask

Flask 是 Python 编写的一款轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2。Flask 使用 BSD 授权。其中两个环境依赖是 Werkzeug 和 jinja2,这意味着它不需要依赖外部库。正因如此,我们将其称为轻量级框架。

Flask 会话使用签名 cookie 让用户查看和修改会话内容。它会记录从一个请求到另一个请求的信息。不过,要想修改会话,用户必须有密钥 Flask.secret_key。

21.当退出Python时,是否释放全部内存?

No。循环引用其它对象或引用自全局命名空间的对象的模块,在 Python 退出时并非完全释放。另外,也不会释放 C 库保留的内存部分。

22. 写一个简单的python socket编程

python 编写server的步骤1第一步是创建socket对象。调用socket构造函数。如socket = socket.socket(family, type ) family参数代表地址家族可为AF_INETAF_UNIXAF_INET家族包括Internet地址,AF_UNIX家族用于同一台机器上的进程间通信。type参数代表套接字类型可为SOCK_STREAM(流套接字)SOCK_DGRAM(数据报套接字)

2.第二步是将socket绑定到指定地址。这是通过socket对象的bind方法来实现的:socket.bind( address )AF_INET所创建的套接字address地址必须是一个双元素元组格式是(host,port)host代表主机port代表端口号。如果端口号正在使用、主机名不正确或端口已被保留,bind方法将引发socket.error异常。

3.第三步是使用socket套接字的listen方法接收连接请求。socket.listen( backlog )backlog指定最多允许多少个客户连接到服务器。它的值至少为1。收到连接请求后,这些请求需要排队,如果队列满,就拒绝请求。

4.第四步是服务器套接字通过socketaccept方法等待客户请求一个连接。connection, address =socket.accept()调用accept方法时socket会时入waiting”状态。客户请求连接时,方法建立连接并返回服务器。accept方法返回一个含有两个元素的元组(connection,address)。第一个元素connection是新的socket对象,服务器必须通过它与客户通信;第二个元素address是客户的Internet地址。

5. 第五步是处理阶段,服务器和客户端通过sendrecv方法通信(传输数据)。服务器调用send,并采用字符串形式向客户发送信息。send方法返回已发送的字符个数。服务器使用recv方法从客户接收信息。调用recv 时,服务器必须指定一个整数,它对应于可通过本次方法调用来接收的最大数据量。recv方法在接收数据时会进入blocked”状态,最后返回一个字符串,用它表示收到的数据。如果发送的数据量超过了recv所允许的,数据会被截短。多余的数据将缓冲于接收端。以后调用recv时,多余的数据会从缓冲区删除(以及自上次调用recv以来,客户可能发送的其它任何数据)

6. 传输结束,服务器调用socketclose方法关闭连接。

python编写client的步骤

1. 创建一个socket以连接服务器socket= socket.socket( family, type )

2.使用socketconnect方法连接服务器。对于AF_INET家族,连接格式如下socket.connect((host,port) )host代表服务器主机名或IPport代表服务器进程所绑定的端口号。如连接成功客户就可通过套接字与服务器通信如果连接失败会引发socket.error异常。

3. 处理阶段,客户和服务器将通过send方法和recv方法通信。

4. 传输结束,客户通过调用socketclose方法关闭连接。

下面给个简单的例子

server.py

if __name__ =='__main__':

import socket

sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

sock.bind(('localhost',8001))

sock.listen(5)

while True:

connection,address =sock.accept()

try:

connection.settimeout(5)

buf =connection.recv(1024)

if buf == '1':

connection.send('welcometo server!')

else:

connection.send('pleasego out!')

except socket.timeout:

print 'time out'

connection.close()

 

client.py

python 代码

if __name__ =='__main__':

import socket

sock =socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.connect(('localhost',8001))

import time

time.sleep(2)

sock.send('1')

print sock.recv(1024)

sock.close()

 在终端运行server.py然后运行clien.py会在终端打印welcometo server!"。如果更改client.pysock.

23.tornado的核心

Tornado 的核心是 ioloop 和 iostream 这两个模块,前者提供了一个高效的 I/O 事件循环,后者则封装了 一个无阻塞的 socket 。通过向 ioloop 中添加网络 I/O 事件,利用无阻塞的 socket ,再搭配相应的回调 函数,便可达到梦寐以求的高效异步执行。

24. post和get

  • GET在浏览器回退时是无害的,而POST会再次提交请求。

  • GET产生的URL地址可以被Bookmark,而POST不可以。

  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。

  • GET请求只能进行url编码,而POST支持多种编码方式。

  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

  • GET请求在URL中传送的参数是有长度限制的,而POST么有。

  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

  • GET参数通过URL传递,POST放在Request body中。

25 string和list互转

list转字符串 .join(list)   字符串转list  list(string)

26. find 和grep

grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。find命令的作用是在目录中搜索文件

27. 如何提高python运行效率

关键代码使用外部功能包;在排序时使用键;对循环的优化

28. yield的用法

yield简单来说就是一个生成器,这样函数它记住上次返回时在函数中的位置。对于生成器第二次(或n次)调用跳转至该函数。

29. 描述数组、链表、队列、堆栈的区别?

数组和链表是数据存储方式的概念,数组在连续的空间中存储数据,而链表可以在非连续的空间中存储数据;队列和堆栈是描述数据存取方式的概念,队列是先进先出,而堆栈是后进先出;队列和堆栈可以用数组来实现,也可以用链表实现。

30.RESTFUL

  • 每一个URI代表一种资源;
  • 客户端和服务器之间,传递这种资源的某种表现层;
  • 客户端通过四个HTTP动词(GET.POST,PUT,DELETE),对服务器端资源进行操作,实现"表现层状态转化".

31. python的常用算法

https://blog.csdn.net/ZhangQiye1993/article/details/81532103

32.open和send

open在post,get都可以,send只能post

 

转载于:https://www.cnblogs.com/chengchengaqin/p/10524256.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值