python 面试题 真题

这些都是去面试的时候,给出的题目,大部分为杭州的公司。由博主整理来的

希望对大家有用,都能找到一份好工作。

 

直接从word复制过来的,排版可能不大美观。

 

一、试列出至少三种目前流行的大型数据库的名称:________、_________、__________,其中您最熟悉的是__________,从__________年开始使用。

Oracle,Mysql,SQLServer   Mysql年份根据自己情况

 

二、有表List,并有字段A、B、C,类型都是整数。表中有如下几条记录:

A

B

C

2

7

9

5

6

4

3

11

9

现在对该表一次完成以下操作:

  1. 查询出B和C列的值,要求按B列升序排列
  2. Select B,C from List order by B AES;
  3. 写出一条新的记录,值为{7,9,8}
  4. Insert into List  values (7,9,8);
  5. 查询C列,要求消除重复的值,按降序排列
  6. Select distinct(C)from List order by C DESC;

 

三、请简要说明数据库视图的作用

1. 数据库视图隐藏了数据的复杂性。
2. 数据库视图有利于控制用户对表中某些列的访问。
3. 数据库视图使用户查询变得简单。
备注:是个虚拟表,本身不存在,但是可以使用.
Mysql:1.基本sql(结构化查询语言)语句2.索引,3.事务,4.视图5.性能优化
 

四、列举您使用过的python网络爬虫所用到的网络数据包(最熟悉的在前):

requests、urllib、urllib2、httplib2
 

五、列举您使用过的python网络爬虫所用到的解析数据包(最熟悉的在前):

BeautifulSoup、Xpath、lxml、pyquery css,正则
 

六、列举您使用过的python中的编码方式(最熟悉的在前):

UTF-8,ASCII,GBK
 

七、python3.5语言中enumerate的意思是_______________________

对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值
enumerate多用于在for循环中得到计数
 

八、99的八进制表示是_______________________

143
 

九、请举出三种常用的排序算法

冒泡、选择、快速
 

十、列出比较熟悉的爬虫框架

Scrapy ,pyspider
 

十一、用4,9,2,7四个数字,可以使用+、-、*和/,每个数字使用一次,使表达式的结果为24,表达式是____9+7+4*2_________________________

十二、对你最有影响的或是您认为最有价值的软件方面的几本书是?

Python 核心编程,利用Python进行数据分析,Python CookBook,Python数据分析与挖掘实战

十三、您最熟悉的Unix环境是____________.Unix下查询环境变量的命令是________,查询脚本定时任务的命令是____________________

AIX,env,crontab

十四、写出在网络爬虫爬取数据的过程中,遇到的防爬虫问题的解决方案

通过headers反爬虫:解决策略,伪造headers
 基于用户行为反爬虫:动态变化去爬取数据,模拟普通用户的行为
 通过动态更改代理ip来反爬虫
 基于动态页面的反爬虫:跟踪服务器发送的ajax请求,模拟ajax请求

十五、阅读以下Python程序

for i in range(5,0,-1):

  print(i)

请在下面写出打印结果

5 4 3 2 1
xrage和range区别?
  1. xrang返回的是生成器,range返回是列表
  2. xrange性能比range快很多
  3. 尤其是返回很大的时候。尽量用xrange吧,除非你是要返回一个列表.
 

十七、post、get有什么区别?

1.参数位置,长度,安全性,使用场景.

1. 根据HTTP规范,GET一般用于获取/查询资源信息,应该是安全的和幂等。而POST一般用于更新资源信息

2. get是在url中传递数据,数据放在请求头中。 post是在请求体中传递数据

3. get传送的数据量较小,只能在请求头上发送数据。post传送的数据量较大,一般被默认为不受限制。

4. get安全性非常低,post安全性较高。但是执行效率却比Post方法好。

十八、 http、https协议有什么区别?

http协议是超文本传输协议,被用于在web浏览器和网站服务器之间传递信息。http协议工作是以明文方式发送内容,不提供任何形式的数据加密,而这也是很容易被黑客利用的地方,如果黑客截取了web浏览器和网站服务器之间的传输信息,就可以直接读懂其中的信息,因此http协议不适合传输一些重要的、敏感的信息,比如信用卡密码及支付验证码等。

安全套接字层https协议就是为了解决http协议的这一安全缺陷而出生的,为了数据传输的安全,https在http的基础上加入了ssl协议,ssl依靠证书来验证服务器的身份,为浏览器和服务器之间的通信加密,这样的话即使黑客截取了发送过程中的信息,也无法破解读懂它,我们网站及用户的信息便得到了最大的安全保障。

 

https协议需要到ca申请证书,一般免费证书很少,需要费用。

http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议

http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。

http的连接很简单,是无状态的, HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全

http协议特点有哪些?

  1. 支持C/S模式,客户端/服务器模式
  2. 简单快速
  3. .灵活
  4. 无状态
  5. 无连接

3、 域名和IP之间有什么关系,如何查看某个域名对应的所有IP?

国际互联网(Internet)上有成千百万台主机(host),为了区分这些主机,人们给每台主机都分配了一个专门的“地址”作为标识,称为IP地址
由于IP地址全是些的数字,为了便于用户记忆,Internet上引进了域名服务系统DNS(Domain Name System)。
当您键入某个域名的时候,这个信息首先到达提供此域名解析的服务器上,再将此域名解析为相应网站的IP地址。完成这一任务的过程就称为域名解析。
 
1.ping  2.nslookup 3.使用站长工具等

 

4、 http协议头中,keep-alive字段有什么作用?选做

HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器都要新建一个连接,完成 之后立即断开连接(HTTP协议为无连接的协议);
当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服 务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。
通过使用keep-alive机制,可以减少tcp连接建立次数,也意味着可以减少TIME_WAIT状态连接,以此提高性能和提高httpd服务器的吞吐率(更少的tcp连接意味着更少的系统内核调用,socket的accept()和close()调用)。

 

5、 robots协议是什么?

Robots协议(也称为爬虫协议、爬虫规则、机器人协议等)也就是robots.txt,网站通过robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。
Robots协议是网站国际互联网界通行的道德规范,其目的是保护网站数据和敏感信息、确保用户个人信息和隐私不被侵犯。因其不是命令,故需要搜索引擎自觉遵守。

 

6、 列出几种常见的关系型数据库和非关系型数据库?(每种至少两个)

Oracle、Mysql、SQLServer、DB2    Redis MongoDB Cassandra

 

7、 内存泄露是什么?如何避免?

Python 默认内存处理机制为GC(垃圾回收)

class People(object):

 

    def __init__(self):

        self.dog = None

        print 'people init'

 

    def __del__(self):

        print 'people del'

 

 

class Dog(object):

    def __init__(self):

        self.p = None

        print 'Dog init'

 

    def __del__(self):

        print 'Dog del'

for i in range(0,10000):

    p1 = People()

    d1 = Dog()

    p1.dog = d1

    d1.p = p1

指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。
内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
导致程序运行速度减慢甚至系统崩溃等严重后果。
 
__del__() 函数的对象间的循环引用是导致内存泄漏的主凶。
 
不使用一个对象时使用:del object 来删除一个对象的引用计数就可以有效防止内存泄漏问题.
通过 Python 扩展模块 gc 来查看不能回收的对象的详细信息
可以通过 sys.getrefcount(obj) 来获取对象的引用计数,并根据返回值是否为 0 来判断是否内存泄漏
 
Python的内存管理机制
1.引用计数:通过引用计数来保持对内存中的变量跟踪,Python内部记录中所有在使用对象各有多少个引用。
Python中有个内部跟踪变量叫做引用计数器,每个变量有多少个引用,简称引用计数。当对象被创建时就创建了一个引用计数。
当某个对象的引用计数为0时,对象就不在需要,就列入了垃圾回收队列。
引用计数增加:1.对象被创建:x=4;2.另外的别人被创建:y=x;3.被作为参数传递给函数:foo(x);4.作为容器对象的一个元素:a=[1,x,'33'];
引用计数减少时:1.一个本地引用离开了它的作用域。比如上面的foo(x)函数结束时,x指向的对象引用减1;
                2.对象的别名被显式的销毁:del x ;或者del y;
                3.对象的一个别名被赋值给其他对象:x=789
                4.对象从一个窗口对象中移除:myList.remove(x)
                5.窗口对象本身被销毁:del myList,或者窗口对象本身离开了作用域。
 
2.垃圾回收
1.引用计数: 每个对象中都有ob-refcnt来做引用计数。当一个对象...,ob-refcnt就会增加,当引用的对象删除,那么ob-refcnt就会减少当ob-refcnt为零,就会释放该对象的内存空间
2.标记清除: 解决循环引用的问题。先按需分配,等到没有空闲内存的时候,从寄存器和程序栈上的引用出发,遍历所有对象和引用把所有能访问的打标记,最后将没有标记的对象释放掉
3.分代技术: 提高效率,提高垃圾回收的效率,按照存活时间,分成不同的集合。将内存块按照其存活时间划分为不同的集合。每个集合就称为一个“代”,垃圾回收的频率随代的存活时间增大而减小。。Python默认定义分代对象集合,引用数越大,对象的存活时间越长
 
3.内存池机制
在Python中,大多数申请的都是小块的内存,会执行大量的malloc和free操作。Python引入了一个内存池机制,用于管理对小块内存的申请和释放,即Pymalloc机制。
它将不用的内存放到内存池而不是返回给操作系统。
1. 当申请的内存小于256字节时,PyObject_Malloc会在内存池中申请内存;当申请的内存大于256字节时,PyObject_Malloc的行为将蜕化为malloc的行为。当然,通过修改Python源代码,我们可以改变这个默认值,从而改变Python的默认内存管理行为。
2. 对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。

 

8、 列举几个常用的dom解析项目、插件

xpath lxml 、 xml、libxml2
前端操作dom使用js或jquery
Jquery是对js进行封装,用法上更简单,效率js更快.(国外用js更多,国内用jquery)
前台向后台传输数据:ajax,它依赖jquery

 

10、如何提高爬取效率?

1.爬取方面,利用异步io。
2.处理方面,利用消息队列做生产者消费者模型
3.多线程
4.多进程
5.分布式
6.提升网速
7.部署高配置服务器中

 

3、 有一个html文本字符串,让我取出<a href="提示我这个链接地址">sflkj</a>这个a标签里面的href的链接地址?

import re

Pattern = re.compile(r'href="(.*?)"')

print Pattern.findall('<a href="提示我这个链接地址">sflkj</a>')[0]

 

from lxml import etree

content = '<a href="提示我这个链接地址">sflkj</a>'

root = etree.fromstring(content)

print root.attrib['href']

 

from bs4 import BeautifulSoup
text = "<a href='提示我这个链接地址'>sflkj</a>"
the_html = BeautifulSoup(text,features='lxml')
print(the_html.find('a').attrs['href'])

 

4、 下面是一个单线程的代码,请改写成多线程的:

start = "http://google.com"
queue = [start]
visited = {start}
while queue:
    url = queue.pop(0)
    print(url)  
    for next_url in extract_url(url):
        if next_url not in visited:
            queue.append(next_url)
        visited.add(next_url)
答案:
from concurrent.futures import ThreadPoolExecutor
 
start = "http://google.com"
queue = [start]
visited = {start}
pool = ThreadPoolExecutor(10)
 
def func(url):
    for next_url in extract_url(url):
        if next_url not in visited:
            queue.append(next_url)
        visited.add(next_url)
 
while queue:
    url = queue.pop(0)
                   pool.submit(func,url)
pool.shutdown(wait=True)

 import time

import random

from concurrent.futures import ThreadPoolExecutor

queue = range(1, 100)

 

 

def do_what(a):

    print a

    time.sleep(10)

    print 'finish'

pool = ThreadPoolExecutor(10)

print pool

while queue:

    pool.submit(do_what, random.randint(0, 10))

pool.shutdown(wait=True)

1、tcp和udp的区别?

TCP(Transmission Control Protocol,传输控制协议)是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来,其中的过程非常复杂,只简单的描述下这三次对话的简单过程:主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机A才向主机B正式发送数据。

  TCP三次握手过程:
  1 主机A通过向主机B 发送一个含有同步序列号的标志位的数据段给主机B ,向主机B 请求建立连接,通过这个数据段,主机A告诉主机B 两件事:我想要和你通信;你可以用哪个序列号作为起始数据段来回应我.
  2 主机B 收到主机A的请求后,用一个带有确认应答(ACK)和同步序列号(SYN)标志位的数据段响应主机A,也告诉主机A两件事:我已经收到你的请求了,你可以传输数据了;你要用哪佧序列号作为起始数据段来回应我
  3 主机A收到这个数据段后,再发送一个确认应答,确认已收到主机B 的数据段:"我已收到回复,我现在要开始传输实际数据了这样3次握手就完成了,主机A和主机B 就可以传输数据了.

  3次握手的特点:
  没有应用层的数据
  SYN这个标志位只有在TCP建产连接时才会被置1
  握手完成后SYN标志位被置0

  TCP建立连接要进行3次握手,而断开连接要进行4次:
  1 当主机A完成数据传输后,将控制位FIN置1,提出停止TCP连接的请求
  2  主机B收到FIN后对其作出响应,确认这一方向上的TCP连接将关闭,将ACK置1
  3 由B 端再提出反方向的关闭请求,将FIN置1
  4 主机A对主机B的请求进行确认,将ACK置1,双方向的关闭结束.
  由TCP的三次握手和四次断开可以看出,TCP使用面向连接的通信方式,大大提高了数据通信的可靠性,使发送数据端和接收端在数据正式传输前就有了交互,为数据正式传输打下了可靠的基础。

UDP(User Data Protocol,用户数据报协议)
  (1) UDP是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
  (2) 由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。
  (3) UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。
  (4) 吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。
  (5)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表(这里面有许多参数)。
  (6)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界,因此,应用程序需要选择合适的报文大小。
  我们经常使用“ping”命令来测试两台主机之间TCP/IP通信是否正常,其实“ping”命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。

 

2、对内存中栈和堆的了解?

内存结构:1.堆区,栈区,全局区,文字常量区,程序代码区.

  栈:

 什么是栈,它是你的电脑内存的一个特别区域,它用来存储被每一个function(包括mian()方法)创建的临时变量。栈是FILO,就是先进后出原则的结构体,它密切的被CPU管理和充分利用。每次function声明一个新的变量,它就会被“推”到栈中。然后每次一个function退出时,所有关于这个函数中定义的变量都会被释放(换句话说就是删除)。一旦栈中的变量释放,这块区域就会变成可用的,提供给其他栈中的变量。

 用栈存储变量的好处是,内存是被你管理的。你不用手动的创建内存,不用当你不在需要它的时候手动释放内存。另外,由于CPU组织栈内存很高效。读出和写入栈变量是很快的。

      理解栈的关键是理解概念,当一个function退出时,所有它的变量都会从栈中弹出,以后都会永远消失。因此栈中的变量本质是局部的。这和我们原来理解为变量作用域或者本地或者全局变量是相关的。在C中,一个公共的bug 是从你程序中的一个function外尝试访问一个在栈中的这个function的变量(在该function已经退出后)。

     关于栈的另一个特点我们应该记住,就是存储在栈中的变量的大小有限制。而堆上创建变量不用考虑。

     总结栈:

      a、栈的伸长和伸缩就是函数压入或者推出局部变量。

      b、我们不用自己去管理内存,变量创建和释放都是自动的。

      c、栈中的变量只有在函数创建运行时存在。

  堆:

       堆也是我们的计算机内存中的一个区域,但是他不是自动管理的。而且也不是被CPU密切的管理着。它是一片更加自由的内存区域(很大)。要想在堆上创建内存,我们必须使用malloc() 或者calloc(),他们都是C语言编译的。一旦你在堆上分配内存,当你不在需要的时候你必须用free()去销毁。如果你不销毁或者销毁失败,你的程序就会有内存泄露。换句话说就是堆内存会一直在,其他进程无法使用。

     不像栈,堆没有变量大小的限制(除了你电脑的物理限制条件外)。堆内存读出和写入都比较慢,因为它必须使用指针图访问堆内存。

  栈和堆的优缺点:(背下来)

      栈:

          a、快速访问。

          b、没有必要明确的创建分类变量,因为它是自动管理的。

          c、空间被CPU高效地管理着,内存不会变成碎片。

          d、只有局部变量

          e、受限于栈大小(取决于操作系统)

          f、变量不能调整大小。

        堆:

          a、变量可以被全局访问

          b、没有内存大小限制

          c、(相对)访问比较慢

          d、没有高效地使用空间,随着块内存的创建和销毁,内存可能会变成碎片。

          e、你必须管理内存(变量的创建和销毁你必须要负责)

          f、变量大小可以用realloc( )调整

 

 

3、爬虫框架scrapy的工作流程

  a、spider解析下载器下下来的response,返回item或是links

  b、item或者link经过spidermiddleware的process_spider_out( )方法,交给engine

  c、engine将item交给item pipeline ,将links交给调度器

  d、在调度器中,先将requests对象利用scrapy内置的指纹函数生成一个指纹对象

  e、如果requests对象中的don't filter参数设置为False,并且该requests对象的指纹不在信息指纹的队列中,那么就把该request对象放到优先级队列中

  f、从优先级队列中获取request对象,交给engine

  g、engine将request对象交给下载器下载,期间会通过downloadmiddleware的process_request方法

  h、下载器完成下载,获得response对象,将该对象交给engine,期间会经过downloadmiddleware的process_response( )方法

  i、engine将获得的response对象交给spider进行解析,期间会经过spidermiddleware的process_spider_input()的方法

  j、从a开始循环

 

4、字典、列表查询时的时间复杂度是怎样的?  

  列表是序列,可以理解为数据结构中的数组,字典可以理解为数据结构中的hashmap,python中list对象的存储结构采用的是线性表,因此其查询复杂度为O(n),而dict对象的存储结构采用的是散列表(hash表),其在最优情况下查询复杂度为O(1)。dict的占用内存稍比list大,会在1.5倍左右。

5、递归中如果没有终止条件会怎样?

  概念:递归算法是一种直接或者间接的调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的。

  特点:

  ①递归就是在过程或者函数里调用自身。

  ②在使用递归策略时,必须有一个明确的递归条件,称为递归出口。

  ③递归算法解题通常显得很简洁,但递归算法解题的效率较低。所以一般不倡导使用递归算法设计程序。

  ④在递归调用的过程当中系统的每一层的返回点、局部变量等开辟了栈来存储。递归函数次数过多容易造成栈溢出等。 所以一般不倡导用递归算法设计程序

  递归如果没有终止条件会导致递归调用成为死循环而不能正常结束,并且会造成栈溢出

笔试:递归计算1到100的阶乘

 Def jcc(num):

   If num<=1:

      Return 1

   Return num*jcc(num-1)

Or = jcc(100)

Print Or

  1、去除列表中的重复元素

 test_list = [1, 2, 3, 4, 5, 5, 7, 2]

# result_list = []

# for a in test_list:

#     if a not in result_list:

#         result_list.append(a)

# print result_list

print list(set(test_list))

  2、得到列表的一个子列表,该列表满足列表中的元素在原列表中是连续的,且子列表的所有元素之和最大。例如[1, -2, 3, -1, 2] => [3, -1, 2]

#如果列表中只有一个元素就有一种情况

#1 -- 1

#2 -- 3

#3 -- 6

#4 -- 10

#5 -- 15

#6 -- 21

#n -- 1到n的和

1、多线程和多进程有什么区别?

  线程:

  线程是操作系统能够进行运算调度的最小单位(程序执行流的最小单元)。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

  一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

  线程是程序中一个单一的顺序控制流程进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。

  进程:

  进程由至少一个线程组成。进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。里面包含对各种资源的调用,内存的管理,网络接口的调用等。。。对各种资源管理的集合 就可以称为 进程

  区别:

  (1)线程共享内存空间;进程的内存是独立的

  (2)同一个进程的线程之间可以直接交流;两个进程想通信,必须通过一个中间代理来实现

  (3)创建新线程很简单; 创建新进程需要对其父进程进行一次克隆

  (4)一个线程可以控制和操作同一进程里的其他线程;但是进程只能操作子进程

  (5)改变主线程(如优先权),可能会影响其它线程;改变父进程,不影响子进程  

2、http请求的header包含哪些信息?

  包含:user-agent、referer、cookie、host、Cache-Control等。

3、爬取的内容怎么去重?

  利用数据库,根据信息的特定字段去重。根据数据和url去去重;根据scrapy自带的去重;还可以用md5对内容加密后再比较

 

笔试

  1、计算n的阶乘,不要使用递归

def factorial(n):
    x = 1
    for i in range(1, n+1):
        x = x * i
    return x

  2、用正则匹配手机号码

re.compile(r'1[3578]\d{9}')
String regex = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8}$"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Python基础面试题

1、什么是lambda函数?它有什么好处?另外python在函数编程方面提供了些什么函数和语法?

lambda是Python中的匿名函数。它语法简单,简化代码,不会产生命名冲突,污染命名空间。Python提供了map,reduce,filter等函数方法,提供了装饰器,闭包等语法
闭包: 如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。
 
Python 用过哪些装饰器?如何自定义装饰器?(百度)

 

2、详细说说tuple、list、dict的用法,它们的特点;

tuple 元祖,固定长度不可变的顺序容器,访问效率高,适合存储一些常量数据,可以作为字典的键使用
list 列表,是长度可变有序的数据存储容器,。可以通过下标索引取到相应的数据
dict 字典,长度可变的hash字典容器。存储的方式为键值对,可以通过相应的键获取相应的值,key支持多种类型
备注:不可变类型可以充当字典的key,例如:字符串,元组等

 

3、说说python中装饰器、迭代器的用法;描述下dict 的 items() 方法与 iteritems() 方法的不同;

装饰器是指对函数执行过程,做一些扩展,甚至可以更改本身函数的执行
迭代器是指遵循迭代器协议的对象,这类对象在被for循环时,每次迭代生成下一个项,不用一开始就生成整个列表
在python3中 不存在iteritems,items方法返回可迭代对象
在python2中 items()返回[(key,value)]的列表对象,iteritems()返回迭代器对象,iteritems()循环时不可以增删dict的内容

 

4、讲讲对unicode, gbk, utf-8等的理解,python2.x是如何处理编码问题?

unicode编码:为了解决各个国家的语言的存储,引进的unicode码,包括UCS2,UCS4,UTF-8,UTF-7
gbk:和unicode不一样的编码方式 ,常用的为 gbk-2312
utf-8: UTF-8 使用 1-4 个字节来存储单个字符,应该是目前最流行的字符集。Linux 默认字符集就是UTF-8。既解决了大多数语言的编码方式,又避免了简单字符存储对空间的浪费
 
python 2.x 需要在文件上方声明文件的编码方式# -*- coding: utf8 -*-,可以通过str.decode/str.encode处理字符串的文本编码
保证 python 编辑器的编码正确,或使用 u’中文’保证被转换成 unicode 编码,推荐使用sys.setdefaultencoding('utf-8')来保证我们的编码

备注:python3默认是utf-8,几乎不存在编码问题

5、Python 是如何进行内存管理的?python 的程序会内存泄露吗?说说有没有什么方面防止或检测内存泄露?

备注:iOS使用的内存管理机制是MRC(手动引用计数管理)和ARC(自动引用计数管理).

Python GC主要使用 引用计数 来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”解决容器对象可能产生的循环引用问题。通过以空间换时间的方法提高垃圾回收效率.
1、引用计数: 每个对象中都有ob-refcnt来做引用计数。当一个对象被创建,ob-refcnt就会增加,当引用的对象删除,那么ob-refcnt就会减少,当ob-refcnt为零,就会释放该对象的内存空间
2、标记清除: 解决循环引用的问题。先按需分配,等到没有空闲内存的时候,从寄存器和程序栈上的引用出发,遍历所有对象和引用把所有能访问的打标记,最后将没有标记的对象释放掉
3、分代技术: 提高效率,提高垃圾回收的效率,按照存活时间,分成不同的集合。将内存块按照其存活时间划分为不同的集合。每个集合就称为一个“代”,垃圾回收的频率随代的存活时间增大而减小。。Python默认定义分代对象集合,引用计数越大,对象的存活时间越长.
 
Python也会内存泄露,Python本身的垃圾回收机制无法回收重写了__del__的循环引用的对象
 
程序员管理好每个python对象的引用,尽量在不需要使用对象的时候,断开所有引用
尽量少通过循环引用组织数据,可以改用weakref叫做弱引用或者用id之类的句柄访问对象
通过gc模块的接口可以检查出每次垃圾回收有哪些对象不能自动处理,再逐个逐个处理

 

6、关于 python 程序的运行性能方面,有什么手段能提升性能?

1、使用多进程,充分利用机器的多核性能
2、对于性能影响较大的部分代码,可以使用C或C++编写
3、对于IO阻塞造成的性能影响,可以使用IO多路复用来解决
4、尽量使用python的内建函数
5、尽量使用局部变量
6 多线程本身也能提升其性能,可以避免项目整体卡顿.但是python没有真正意义多线程,因为存在GIL(全局解释锁)

备注:python中用过哪些内建函数:如字典的,字符串,列表的

7、list 对象 alist [{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}], 请按 alist 中元素的age 由大到小排序;

def sort_by_age(list1):
    return sorted(alist,key=lambda x:x['age'],reverse=True)

 

8、两个 list 对象 alist ['a','b','c','d','e','f'], blist ['x','y','z','d','e','f'],请用简洁的方法合并这两个 list,并且 list 里面的元素不能重复;

备注:列表拼接尽量不要用加号,因为会生成一个新列表,推荐使用extend

alist = ['a','b','c','d','e','f']
blist = ['x','y','z','d','e','f']
1
def merge_list(*args):
    s = set()
    for i in args:
        s = s.union(i)
return list(s)
2

alist.extend(blist)

print list(set(alist))

9、打乱一个排好序的 list 对象 alist;

import random
random.shuffle(alist)

 

10、简单实现一个stack(栈结构,特点:先入后出 FILO:First In Last Out)

栈的一些典型功能:push(入栈),pop(出栈),top(栈顶),empty(栈为空),size(栈的大小)

class Stack:
    def __init__(self):
        self.items = []
 
    def __iter__(self):
        return self.items.__iter__()
 
    def pop(self):
        return self.items.pop()
 
    def top(self):
        if len(self.items) > 0:
            return self.items[len(self.items) - 1]
 
    def push(self, item):
        self.items.append(item)
 
    def empty(self):
        self.items = []
 
    def size(self):
        return len(self.items)

补充:已知A,B,C,D,E五个字母按照顺序进栈和出栈,那么有没有可能出栈顺序变成B,A,C,E,D/CABED(不可能:如果C先出,A和B肯定进去了,然后A不可能比B先出来)

答:A进,B进,B出,A出,C进C出,D进,E进,E出,D出

11、输入某年某月某日,判断这一天是这一年的第几天?(可以用 python 标准库)

import datetime
def dayofyear():
    year = input("请输入年份:")
    month = input("请输入月份:")
    day = input("请输入天:")
    date1=datetime.date(year=int(year),month=int(month),day=int(day))
    date2=datetime.date(year=int(year),month=1,day=1)
    return (date1 -date2).days

 

12、将字符串:"k:1|k1:2|k2:3|k3:4",处理成 python 字典:{k:1, k1:2, ... }

str1 = "k:1|k1:2|k2:3|k3:4"
def str2dict(str1):
    dict1 = {}
    for iterms in str1.split('|'):
        key,value = iterms.split(':')
        dict1[key] = value
return dict1
 
import json
str1 = "k:1|k1:2|k2:3|k3:4"
str1 = str1.replace('|', '","')
str1 = str1.replace(':', '":"')
str2 = '{"'+str1+'"}'
print str2
print json.loads(str2)

os.path和sys.path的区别?

os.path是module,包含了各种处理长文件名(路径名)的函数。

sys.path是由目录名构成的列表,Python 从中查找扩展模块( Python 源模块, 编译模块,或者二进制扩展). 启动 Python 时,这个列表从根据内建规则,PYTHONPATH 环境变量的内容, 以及注册表( Windows 系统)等进行初始化.

Python里面如何拷贝一个对象?deepcopy 和 copy的区别?

http://www.cnblogs.com/xueli/p/4952063.html

 

copy 仅拷贝对象本身,而不拷贝对象中引用的其它对象。

deepcopy 除拷贝对象本身,而且拷贝对象中引用的其它对象。

re模块中match和search方法的不同?

match() 函数只检查 RE 是否在字符串开始处匹配,而search() 则是扫描整个字符串。

解释生成器(generator)与函数的不同,并实现和使用简单generator?

生成器和函数的主要区别在于函数 return avalue,生成器 yield a value同时标记或记忆point of the yield 以便于在下次调用时从标记点恢复执行。 yield 使函数转换成生成器,而生成器反过来又返回迭代器。

dict 的 items() 方法与 iteritems() 方法的不同?

items方法将所有的字典以列表方式返回,其中项在返回时没有特殊的顺序;

iteritems方法有相似的作用,但是返回一个迭代器对象

python后台面试题

 

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

Django源自一个在线新闻 Web站点,于 2005 年以开源的形式被释放出来。

Django 框架的核心组件有:

用于创建模型的对象关系映射为最终用户设计的完美管理界面一流的 URL 设计设计者友好的模板语言缓存系统等等

它鼓励快速开发,并遵循MVC设计。Django遵守 BSD版权,最新发行版本是Django1.4,于2012年03月23日发布.Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用,多个组件可以很方便的以“插件”形式服务于整个框架,Django有许多功能强大的第三方插件,你甚至可以很方便的开发出自己的工具包。这使得Django具有很强的可扩展性。它还强调快速开发和DRY(Do Not RepeatYourself)原则。

Tornado是 FriendFeed使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像 web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具和优化。

Tornado 和现在的主流 Web 服务器框架(包括大多数Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对epoll的运用,Tornado 每秒可以处理数以千计的连接,这意味着对于实时 Web服务来说,Tornado 是一个理想的 Web 框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接。(关于如何扩容 服务器,以处理数以千计的客户端的连接的问题。

解释下django-debug-toolbar的使用

使用django开发站点时,可以使用django-debug-toolbar来进行调试。在settings.py中添加’debug_toolbar.middleware.DebugToolbarMiddleware’到项目的MIDDLEWARE_CLASSES 内。

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

为了能在Django中使用redis,还需要安装redis for Django的插件。然后在Django的settings中配置了。现在连接和配置都已经完成了,接下来是一个简单的例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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)

 

 

MySQL锁有几种;死锁是怎么产生的;
为何,以及如何分区、分表;
MySQL的char varchar text的区别;
了解join么,有几种,有何区别,A LEFT JOIN B,查询的结果中,B没有的那部分是如何显示的(NULL);
索引类型有几种,BTree索引和hash索引的区别(我没答上来这俩在磁盘结构上的区别);
手写:如何对查询命令进行优化;
NoSQL了解么,和关系数据库的区别;redis有几种常用存储类型;

 

 

都是让简单的介绍下你在公司的项目,不管是不是后端相关的,主要是要体现出你干了什么;
你在项目中遇到最难的部分是什么,你是怎么解决的;
你看过django的admin源码么;看过flask的源码么;你如何理解开源;
MVC / MTV;
缓存怎么用;
中间件是干嘛的;
CSRF是什么,django是如何避免的;XSS呢;
如果你来设计login,简单的说一下思路;
session和cookie的联系与区别;session为什么说是安全的;

https://www.jianshu.com/p/4ce62bcbfb82
uWSGI和Nginx的作用;

https://blog.csdn.net/lihao21/article/details/52304119
(我发现基本不问django实现细节相关的东西。。或者问也问的很少,哎,之前准备的方向完全错了)

猜你喜欢

转载自blog.csdn.net/Gents_hu/article/details/88054046
今日推荐