2017年7月19日面试后记

由于基础学的不牢,导致场面一度十分尴尬......

一个冒泡排序都憋半天还写错了.....我深深的感受到了自己好菜

我决定以后每天抽时间补补算法和数据结构的基础

今天答不上来和答的不好的问题,去查了一下:

1.迭代

其实迭代就是用for循环遍历list或tuple。

关于这个问题面试官提到的是yield,他应该是想问关于生成器的问题吧。

顺便提一下迭代器:

实际上for循环也可以对其他对象进行迭代,只要该对象实现了__iter__方法。该方法会返回一个迭代器,迭代器就是具有next方法(这个方法在调用时不需要参数)的对象。在调用next方法时,迭代器会返回它的下一个值。如果next方法被调用,但迭代器没有值可以返回,就会引发一个StopIteration异常。

生成器:是一种用普通的函数语法定义的迭代器。

yield是一个表达式,是有返回值的。

当一个函数中含有yield时,它不再是一个普通的函数,而是一个生成器.当该函数被调用时不会自动执行,而是暂停。

但它不是像return那样返回值,而是每次产生多个值。每次产生一个值,函数就会被冻结:即函数停在那点等待被重新唤醒。函数被重新唤醒后就从停止的那点开始执行。

从别处看到了几个例子:

例1:

[python] view plain copy
 
  1. >>> def mygenerator():  
  2. ...     print 'start...'  
  3. ...     yield 5  
  4. ...   
  5. >>> mygenerator()            //在此处调用,并没有打印出start...说明存在yield的函数没有被运行,即暂停  
  6. <generator object mygenerator at 0xb762502c>  
  7. >>> mygenerator().next()     //调用next()即可让函数运行.  
  8. start...  
  9. 5  
  10. >>>   

如一个函数中出现多个yield则next()会停止在下一个yield前,见例2:

例2:

[python] view plain copy
 
  1. >>> def fun2():  
  2. ...     print 'first'  
  3. ...     yield 5  
  4. ...     print 'second'  
  5. ...     yield 23  
  6. ...     print 'end...'  
  7. ...   
  8. >>> g1 = fun2()  
  9. >>> g1.next()             //第一次运行,暂停在yield 5               
  10. first  
  11. 5  
  12. >>> g1.next()             //第二次运行,暂停在yield 23  
  13. second  
  14. 23  
  15. >>> g1.next()             //第三次运行,由于之后没有yield,再次next()就会抛出错误  
  16. end...  
  17. Traceback (most recent call last):  
  18.   File "<stdin>", line 1, in <module>  
  19. StopIteration  
  20. >>>   

为什么yield 5会输出5,yield 23会输出23? 

我们猜测可能是因为yield是表达式,存在返回值.

那么这是否可以认为yield 5的返回值一定是5吗?实际上并不是这样,这个与send函数存在一定的关系,这个函数实质上与next()是相似的,区别是send是传递yield表达式的值进去,而next不能传递特定的值,只能传递None进去,因此可以认为g.next()和g.send(None)是相同的。见例3:

例3:

 
  1. >>> def fun():  
  2. ...     print 'start...'  
  3. ...     m = yield 5  
  4. ...     print m  
  5. ...     print 'middle...'  
  6. ...     d = yield 12  
  7. ...     print d  
  8. ...     print 'end...'  
  9. ...   
  10. >>> m = fun()              //创建一个对象  
  11. >>> m.next()               //会使函数执行到下一个yield前  
  12. start...  
  13. 5  
  14. >>> m.send('message')      //利用send()传递值  
  15. message                    //send()传递进来的   
  16. middle...  
  17. 12  
  18. >>> m.next()  
  19. None                       //可见next()返回值为空  
  20. end...  
  21. Traceback (most recent call last):  
  22.   File "<stdin>", line 1, in <module>  
  23. StopIteration  

2.python实现二叉树

树的遍历主要有两种,一种是深度优先遍历,像前序、中序、后序;还有一种是广度优先遍历。像层次遍历。=

深度优先一般用递归,广度优先一般用队列。普通情况下能用递归实现的算法大部分也能用堆栈来实现。

# _*_ encoding:utf-8 _*_
__author__ = 'xyx'
__date__ = '2017-7-20 22:41'

#coding=utf-8

class Node(object):
"""节点类"""
def __init__(self, elem=-1, lchild=None, rchild=None):
self.elem = elem
self.lchild = lchild
self.rchild = rchild


class Tree(object):
"""树类"""
def __init__(self):
self.root = Node()


def add(self, elem):
"""为树加入节点"""
node = Node(elem)
if self.root.elem == -1: #假设树是空的。则对根节点赋值
self.root = node
else:
myQueue = []
treeNode = self.root
myQueue.append(treeNode)
while myQueue: #对已有的节点进行层次遍历
treeNode = myQueue.pop(0)
if treeNode.lchild == None:
treeNode.lchild = node
return
elif treeNode.rchild == None:
treeNode.rchild = node
return
else:
myQueue.append(treeNode.lchild)
myQueue.append(treeNode.rchild)


def front_digui(self, root):
"""利用递归实现树的先序遍历"""
if root == None:
return
print (root.elem),
self.front_digui(root.lchild)
self.front_digui(root.rchild)


def middle_digui(self, root):
"""利用递归实现树的中序遍历"""
if root == None:
return
self.middle_digui(root.lchild)
print (root.elem),
self.middle_digui(root.rchild)


def later_digui(self, root):
"""利用递归实现树的后序遍历"""
if root == None:
return
self.later_digui(root.lchild)
self.later_digui(root.rchild)
print (root.elem),


def front_stack(self, root):
"""利用堆栈实现树的先序遍历"""
if root == None:
return
myStack = []
node = root
while node or myStack:
while node: #从根节点開始,一直找它的左子树
print (node.elem),
myStack.append(node)
node = node.lchild
node = myStack.pop() #while结束表示当前节点node为空,即前一个节点没有左子树了
node = node.rchild #開始查看它的右子树


def middle_stack(self, root):
"""利用堆栈实现树的中序遍历"""
if root == None:
return
myStack = []
node = root
while node or myStack:
while node: #从根节点開始。一直找它的左子树
myStack.append(node)
node = node.lchild
node = myStack.pop() #while结束表示当前节点node为空。即前一个节点没有左子树了
print (node.elem),
node = node.rchild #開始查看它的右子树


def later_stack(self, root):
"""利用堆栈实现树的后序遍历"""
if root == None:
return
myStack1 = []
myStack2 = []
node = root
myStack1.append(node)
while myStack1: #这个while循环的功能是找出后序遍历的逆序,存在myStack2里面
node = myStack1.pop()
if node.lchild:
myStack1.append(node.lchild)
if node.rchild:
myStack1.append(node.rchild)
myStack2.append(node)
while myStack2: #将myStack2中的元素出栈,即为后序遍历次序
print (myStack2.pop().elem),


def level_queue(self, root):
"""利用队列实现树的层次遍历"""
if root == None:
return
myQueue = []
node = root
myQueue.append(node)
while myQueue:
node = myQueue.pop(0)
print (node.elem),
if node.lchild != None:
myQueue.append(node.lchild)
if node.rchild != None:
myQueue.append(node.rchild)


if __name__ == '__main__':
"""主函数"""
elems = range(10) #生成十个数据作为树节点
tree = Tree() #新建一个树对象
for elem in elems:
tree.add(elem) #逐个加入树的节点

print ('队列实现层次遍历:')
tree.level_queue(tree.root)

print (' 递归实现先序遍历:')
tree.front_digui(tree.root)
print (' 递归实现中序遍历:')
tree.middle_digui(tree.root)
print (' 递归实现后序遍历:')
tree.later_digui(tree.root)

print (' 堆栈实现先序遍历:')
tree.front_stack(tree.root)
print (' 堆栈实现中序遍历:')
tree.middle_stack(tree.root)
print (' 堆栈实现后序遍历:')
tree.later_stack(tree.root)

3.用python实现冒泡排序

好久没看数据结构,这么简单还是忘了......

array = [1,2,3,6,5,4]

for i in range(len(array)-1):
    for j in range(len(array)-1-i):
    if array[j] > array[j + 1]:
        array[j+1], array[j] = array[j], array[j+1]
print(array)


4.restful风格

 这个确实不知道,大致差了一下restful风格的特点如下

1.资源

所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。资源总要通过某种载体反应其内容,文本可以用txt格式表现,也可以用HTML格式、XML格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现;JSON是现在最常用的资源表示格式。

结合我的开发实践,我对资源和数据理解如下:

资源是以json(或其他Representation)为载体的、面向用户的一组数据集,资源对信息的表达倾向于概念模型中的数据:

  • 资源总是以某种Representation为载体显示的,即序列化的信息
  • 常用的Representation是json(推荐)或者xml(不推荐)等
  • Represntation 是REST架构的表现层

相对而言,数据(尤其是数据库)是一种更加抽象的、对计算机更高效和友好的数据表现形式,更多的存在于逻辑模型中

资源和数据关系如下:

resource vs data

2 统一接口

RESTful架构风格规定,数据的元操作,即CRUD(create, read, update和delete,即数据的增删查改)操作,分别对应于HTTP方法:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源,这样就统一了数据操作的接口,仅通过HTTP方法,就可以完成对数据的所有增删查改工作。

即:

  • GET(SELECT):从服务器取出资源(一项或多项)。
  • POST(CREATE):在服务器新建一个资源。
  • PUT(UPDATE):在服务器更新资源(客户端提供完整资源数据)。
  • PATCH(UPDATE):在服务器更新资源(客户端提供需要修改的资源数据)。
  • DELETE(DELETE):从服务器删除资源。

3 URI

可以用一个URI(统一资源定位符)指向资源,即每个URI都对应一个特定的资源。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或识别符。

一般的,每个资源至少有一个URI与之对应,最典型的URI即URL。

4 无状态

所谓无状态的,即所有的资源,都可以通过URI定位,而且这个定位与其他资源无关,也不会因为其他资源的变化而改变。有状态和无状态的区别,举个简单的例子说明一下。如查询员工的工资,如果查询工资是需要登录系统,进入查询工资的页面,执行相关操作后,获取工资的多少,则这种情况是有状态的,因为查询工资的每一步操作都依赖于前一步操作,只要前置操作不成功,后续操作就无法执行;如果输入一个url即可得到指定员工的工资,则这种情况是无状态的,因为获取工资不依赖于其他资源或状态,且这种情况下,员工工资是一个资源,由一个url与之对应,可以通过HTTP中的GET方法得到资源,这是典型的RESTful风格。

state

stateless

5.http协议

我理解的应该是简述一下http协议吧

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。

HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。

HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出。

HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。

http协议的特点:

1、简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。

2、灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。

3.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

4.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
5.支持B/S及C/S模式。

原文地址:https://www.cnblogs.com/xyxpython/p/7208940.html