python面试笔试精选
-
解释语言的特性有什么?非独立性,效率低
-
python2.x和python3.x的区别?
-
__unicode__
改为__str__
描述类方法 - Python 2 有 ASCII str() 类型,unicode() 是单独的,不是 byte 类型。现在, 在 Python 3,我们最终有了 Unicode (utf-8) 字符串,以及一个字节类:byte 和 bytearrays。
- print由语句改为方法
- /不再取整
- python3中没有旧式类
- 添加了库 asyncio等
- xrange整合到range中和iteritems
- 去除了.next()方法用,next()函数来代替
- input()输入转为了str()对象
-
-
python中的with语句?
- with是用来简化try finally代码的,上下文管理器实现了
__enter__()
和__exit()__
方法。__enter__()
方法返回了一个对象复制给as后面的变量。通常
return Fasle来向外层捕获异常。
- with是用来简化try finally代码的,上下文管理器实现了
-
什么是GIL?
- 任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。多线程的并发则成为不可能。
-
说说decotator的用法和场景
- 所谓装饰器就是把函数包装一下,为函数添加一些附加功能,装饰器就是一个函数,参数为被包装的函数,返回包装后的函数:
import datetime
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args,**kw):
d1 = datetime.datetime.now()
back = func(*args,**kw)
print('excute in %s' % str(datetime.datetime.now() -d1))
return back
return wrapper
-
inspect模块有什么用?
- 用于自省也叫反射,运行时动态获取未知对象的信息。
- 对是否是模块,框架,函数等进行类型检查。
- 获取类或函数的参数的信息,例如dir()
-
介绍一下python中webbrowser的用法
webbrowser模块提供了一个高级接口来显示基于Web的文档,大部分情况下只需要简单的调用open()方法。webbrowser定义了如下的异常:exception webbrowser.Error, 当浏览器控件发生错误是会抛出这个异常 webbrowser有以下方法:
webbrowser.open(url[, new=0[, autoraise=1]])
这个方法是在默认的浏览器中显示url, 如果new = 0, 那么url会在同一个浏览器窗口下打开,如果new = 1, 会打开一个新的窗口,如果new = 2, 会打开一个新的tab, 如果autoraise = true, 窗口会自动增长。
webbrowser.open_new(url)
在默认浏览器中打开一个新的窗口来显示url, 否则,在仅有的浏览器窗口中打开url
webbrowser.open_new_tab(url)
在默认浏览器中当开一个新的tab来显示url, 否则跟open_new()一样
webbrowser.get([name]) 根据name返回一个浏览器对象,如果name为空,则返回默认的浏览器
webbrowser.register(name, construtor[, instance])
注册一个名字为name的浏览器,如果这个浏览器类型被注册就可以用get()方法来获取。
-
python实现单例模式
-
__new__
方法
-
class Singleton(object):
def __new__(cls):
# 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance
obj1 = Singleton()
obj2 = Singleton()
obj1.attr1 = 'value1'
print obj1.attr1, obj2.attr1
print obj1 is obj2
- 共享属性
class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob
class MyClass2(Borg):
a = 1
one = MyClass2()
two = MyClass2()
#one和two是两个不同的对象
#但是one和two具有相同的(同一个__dict__属性),见:
print id(one.__dict__)
#30104000
print id(two.__dict__)
#30104000
- 装饰器版本
import functools
def singleton(cls):
instances = {}
@functool.wraps(cls)
def getinstance(*args, **kw):
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance
@singleton
class MyClass:
- import 模式
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton()
# to use
from mysingleton import my_singleton
my_singleton.foo()
-
__init__
和__new__
的区别-
__init__
通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。 -
__new__
通常用于控制生成一个新实例的过程。它是类级别的方法。
-
-
如何用python发送邮件?
- 用email构造邮件,smtplib负责发送邮件
from email.mime.text import MIMEText
msg = MIMEText('hello, send by Python...', 'plain', 'utf-8')
# 输入Email地址和口令:
from_addr = input('From: ')
password = input('Password: ')
# 输入收件人地址:
to_addr = input('To: ')
# 输入SMTP服务器地址:
smtp_server = input('SMTP server: ')
import smtplib
server = smtplib.SMTP(smtp_server, 25) # SMTP协议默认端口是25
server.set_debuglevel(1)
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string())
server.quit()
```
* ###python文件操作?
* `os.remove(filename) `
* `shutil.copyfile('a.py','')`
* ###写一个简单的socket编程
* 客户端
```python
import socket
#创建socket对象
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#建立连接
s = connect(('www.sina.com',80))
#发送数据
s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')
#接受数据
buffer = []
while True:
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
data = b''.join(buffer)
s.close()
* 服务端
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#监听端口
s.bind(('127.0.0.1',9999))
#调用listen()方法开始监听端口,传入的参数指定等待连接的最大数量
s.listen(5)
while True:
#接受一个新连接
sock,addr = s.accept()
#创建新线程处理TCP连接
t = threading.Thread(target=tcplink,args=(sock,addr))
t.start()
```
```python
def tcplink(sock,addr):
sock.send(b'welcome')
while True:
data = sock.recv(1024)
time.sleep(1)
if not data or data.decode('utf-8') == 'exit':
break
sock.send('hello %s ' % data.decode('utf-8').encode('utf-8'))
sock.close()
-
静态函数, 类函数, 成员函数的区别?
-
静态函数(@staticmethod): 即静态方法,主要处理与这个类的逻辑关联, 如验证数据;
-
类函数(@classmethod):即类方法, 更关注于从类中调用方法, 而不是在实例中调用方法, 如构造重载;
-
成员函数: 实例的方法, 只能通过实例进行调用;
def foo(x): print "executing foo(%s)"%(x) class A(object): def foo(self,x): print "executing foo(%s,%s)"%(self,x) @classmethod def class_foo(cls,x): print "executing class_foo(%s,%s)"%(cls,x) @staticmethod def static_foo(x): print "executing static_foo(%s)"%x a=A()
-
-
如何理解WSGI和fastCGI?
- FastCGI是一个可伸缩地、高速地在HTTP server和动态脚本语言间通信的接口。多数流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等
- CGI全称是“公共网关接口”(CommonGateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。 CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如php,perl,tcl等。
- FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute模式)。它还支持分布式的运算, 即 FastCGI 程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。
- FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能。众所周知,CGI解释器的反复加载是CGI性能低下的主要原因,如果CGI解释器保持在内存中并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail- Over特性等等。
- WSGI, Web Server Gateway Interface 。WSGI是python的接口规范,这个规范是针对WEB服务器和python应用(框架等)的交互的。Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。
- WSGI的全称为: PythonWeb Server Gateway Interface v1.0 (Python Web 服务器网关接口),它是 Python 应用程序和 WEB 服务器之间的一种接口。
它的作用,类似于FCGI 或 FASTCGI 之类的协议的作用。 - WSGI 的目标,是要建立一个简单的普遍适用的服务器与 WEB 框架之间的接口。
- Flup就是使用 Python 语言对 WSGI 的一种实现,是可以用于 Python 的应用开发中的一种工具或者说是一种库。
- Spawn-fcgi是一个小程序,这个程序的作用是管理fast-cgi进程,那么管理wsgi进程也是没有问题的,功能和php-fpm类似。故,简单地说,WSGI和FastCGI都是一种CGI,用于连接WEB服务器与应用程序,而WSGI专指Python应用程序。而flup是WSGI的一种实现,Spawn-fcgi是用于管理flup进程的一个工具,可以启动多个wsgi进程,并管理它们。
-
解释一下Django和Tornado的关系和差别
- Django简单、快速开发数据库驱动网站,强调代码的复用,支持MVC,DRY。
- Tornado是非阻塞式的服务器环境,速度快
-
Django中的Redis
- 为了能在Django中使用redis,还需要安装redis for Django的插件。然后在Django的settings中配置了。现在连接和配置都已经完成了,接下来是一个简单的例子
from django.conf import settings
from django.core.cache import cache
#read cache user id
def read_from_cache(self, user_name):
key = 'user_id_of_'+user_name
value = cache.get(key)
if value == None:
data = None
else:
data = json.loads(value)
return data
#write cache user id
def write_to_cache(self, user_name):
key = 'user_id_of_'+user_name
cache.set(key, json.dumps(user_name), settings.NEVER_REDIS_TIMEOUT)
-
解释下http
HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。
HTTP协议的主要特点可概括如下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
-
解释下Http请求头和常见响应状态码
- Accept:指浏览器或其他客户可以接爱的MIME文件格式。可以根据它判断并返回适当的文件格式。
- Accept-Charset:指出浏览器可以接受的字符编码。英文浏览器的默认值是ISO-8859-1.
- Accept-Language:指出浏览器可以接受的语言种类,如en或en-us,指英语。
- Accept-Encoding:指出浏览器可以接受的编码方式。编码方式不同于文件格式,它是为了压缩文件并加速文件传递速度。浏览器在接收到Web响应之后先解码,然后再检查文件格式。
- Cache-Control:设置关于请求被代理服务器存储的相关选项。一般用不到。
- Connection:用来告诉服务器是否可以维持固定的HTTP连接。HTTP/1.1使用Keep-Alive为默认值,这样,当浏览器需要多个文件时(比如一个HTML文件和相关的图形文件),不需要每次都建立连接。
- Content-Type:用来表名request的内容类型。可以用HttpServletRequest的getContentType()方法取得。
- Cookie:浏览器用这个属性向服务器发送Cookie。Cookie是在浏览器中寄存的小型数据体,它可以记载和服务器相关的用户信息,也可以用来实现会话功能。
-
补充:
状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:- 1xx:指示信息--表示请求已接收,继续处理
- 2xx:成功--表示请求已被成功接收、理解、接受
- 3xx:重定向--要完成请求必须进行更进一步的操作
- 4xx:客户端错误--请求有语法错误或请求无法实现
- 5xx:服务器端错误--服务器未能实现合法的请求
- 常见状态代码、状态描述、说明:
- 200 OK //客户端请求成功
- 400 Bad Request //客户端请求有语法错误,不能被服务器所理解
- 401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
- 403 Forbidden //服务器收到请求,但是拒绝提供服务
- 404 Not Found //请求资源不存在,eg:输入了错误的URL
- 500 Internal Server Error //服务器发生不可预期的错误
- 503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
- eg:HTTP/1.1 200 OK (CRLF)
-
简述正则表达式中?p的含义
- python中给所捕获的组自定义命名与常规使用(?<name>expression)的语法不一样,python使用其特定的P标记给捕获的组命名,格式为(?P<name>expression)。
-
3种常用的python框架
- Django 全能型框架,自带模板,ORM支持MVC,快速开发网站
- Flask 小巧,没有orm,配合SQLAlchemy使用
- Tornado 异步开源框架,高并发处理
-
reactor是什么? 有什么作用?请简要描述。
- 异步IO模型需要一个消息循环,在消息循环中,主线程不断地重复“读取消息-处理消息”这一过程。这种等待事件发生的循环体叫做reator。
-
通常在python编写tcp服务时,我们使用拆、粘包的模块是什么?如何加载这个模块
- 粘包:发送方发送两个字符串”hello”+”world”,接收方却一次性接收到了”helloworld”。
-
分包:发送方发送字符串”helloworld”,接收方却接收到了两个字符串”hello”和”world”。
-
有哪些CPython的替代实现?什么时候,为什么会使用他们?
- IPython是基于CPython之上的一个交互式解释器,也就是说,IPython只是在交互方式上有所增强,但是执行Python代码的功能和CPython是完全一样的。
- PyPy是另一个Python解释器,它的目标是执行速度。PyPy采用JIT技术,对Python代码进行动态编译(注意不是解释),所以可以显著提高Python代码的执行速度。
- Jython是运行在Java平台上的Python解释器,可以直接把Python代码编译成Java字节码执行。
- IronPython和Jython类似,只不过IronPython是运行在微软.Net平台上的Python解释器,可以直接把Python代码编译成.Net的字节码。
-
python实现一个stack
class Stack(object):
def __init__(self):
self.stack=[]
def isEmpty(self):
return self.stack==[]
def push(self,item):
self.stack.append(item)
def pop(self):
if self.isEmpty():
raise IndexError,'pop from empty stack'
return self.stack.pop()
def peek(self):
return self.stack[-1]
def size(self):
return len(self.stack)
-
python中单下划线和双下划线
-
__name
表示私有变量,只允许内部访问,外部不能直接访问,但是可以通过_classname__name
来访问。 -
__name__
是特殊变量,可以外部访问,区分自定义变量名,防止冲突。 -
_name
外部是可以访问的,但是按照约定,不要随意访问。
-
-
四匹马比赛的全部结果
horses = [1, 2, 3, 4]
>>> races = itertools.permutations(horses)
>>> print(races)
<itertools.permutations object at 0xb754f1dc>
>>> print(list(itertools.permutations(horses)))
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2),(1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
-
新式类和旧式类
- 新式类继承object,多重继承时,新式类广度优先,旧式类深度优先,MRO属性。
- 新式类的实例有slots属性,和Property功能。
-
python中的拷贝
-
浅拷贝和深拷贝的不同仅仅是对组合对象来说,所谓的组合对象就是包含了其它对象的对象,如列表,类实例。而对于数字、字符串以及其它“原子”类型,没有拷贝一说,产生的都是原对象的引用。
-
所谓“浅拷贝”,是指创建一个新的对象,其内容是原对象中元素的引用。(拷贝组合对象,不拷贝子对象)常见的浅拷贝有:切片操作、工厂函数、对象的copy()方法、copy模块中的copy函数。
-
为什么使用了深拷贝,a和b中元素的id还是一样呢?
答:这是因为对于不可变对象,当需要一个新的对象时,python可能会返回已经存在的某个类型和值都一致的对象的引用。而且这种机制并不会影响 a 和 b 的相互独立性,因为当两个元素指向同一个不可变对象时,对其中一个赋值不会影响另外一个。import copy a = [1, 2, 3, 4, ['a', 'b']] #原始对象 b = a #赋值,传对象的引用 c = copy.copy(a) #对象拷贝,浅拷贝 d = copy.deepcopy(a) #对象拷贝,深拷贝 a.append(5) #修改对象a a[4].append('c') #修改对象a中的['a', 'b']数组对象 print 'a = ', a print 'b = ', b print 'c = ', c print 'd = ', d 输出结果: a = [1, 2, 3, 4, ['a', 'b', 'c'], 5] b = [1, 2, 3, 4, ['a', 'b', 'c'], 5] c = [1, 2, 3, 4, ['a', 'b', 'c']] d = [1, 2, 3, 4, ['a', 'b']]
-
-
python中的垃圾回收机制
-
Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。
-
1 引用计数
PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。
优点:
简单
实时性
缺点:
维护引用计数消耗资源
循环引用 -
2 标记-清除机制
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。
-
3 分代技术
分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。Python默认定义了三代对象集合,索引数越大,对象存活时间越长。
举例: 当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。
-
-
-
TCP三次握手
- 客户端通过向服务器端发送一个SYN来创建一个主动打开,作为三路握手的一部分。客户端把这段连接的序号设定为随机数 A。
- 服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK 的确认码应为 A+1,SYN/ACK 包本身又有一个随机序号 B。
- 最后,客户端再发送一个ACK。当服务端受到这个ACK的时候,就完成了三路握手,并进入了连接创建状态。此时包序号被设定为收到的确认号 A+1,而响应则为 B+1。
-
四次挥手
- 因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
-
urllib和urllib2的区别
- urllib提供urlencode方法用来GET查询字符串的产生,而urllib2没有。这是为何urllib常和urllib2一起使用的原因。
- urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL。这意味着,你不可以伪装你的User Agent字符串等
-
RESTFUL架构? 即Representational State Transfer的缩写。我对这个词组的翻译是"表现层状态转化"。
- 每一个URI代表一种资源;
- 客户端和服务器之间,传递这种资源的某种表现层;
- 客户端通过四个HTTP动词(GET.POST,PUT,DELETE),对服务器端资源进行操作,实现"表现层状态转化"。
-
用规定的Python方法,在一行中对给定的任意整数数列,按照如下规则排序:
- a) 非负数在前,负数在后;
- b) 非负数部分按照从小到大排序;
- c) 负数部分按从大到小排序。
- 如: 数列 foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4]
- 希望排序后为[0,2,4,8,8,9,-2,-4,-4,-5,-20]
sorted(foo, key=lambda x: (x>=0 and -abs(1/float(x+1)) or abs(x)))