一、web框架

  web框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以快速开发特定的系统。他山之石,可以攻玉。python的所有web框架,都是对socket进行封装的。

  web应用本质上是一个socket服务端,用户的浏览器是一个socket客户端。socket处在应用层与传输层之间,是操作系统中I/O系统的延伸部分(接口),负责系统进程和应用之间的通信。【python网络编程基础】

  上面这个解释看起来有点费劲。重新解释一遍:

  socket是在应用层和传输层之间的一个抽象层,扮演“信使”角色。它把tcp/ip层复杂的操作抽象为几个简单的接口以供应用层调用,从而实现在网络中通信。

  django是python web开发的主流框架,另外还有flask和tensorflow。django框架必须掌握,要学精通。

  web应用的流程:

//浏览器发送一个HTTP请求;
//服务器收到请求,根据请求信息,进行函数处理,生成一个HTML文档;
//服务器把HTML文档作为HTTP响应的Body发送给浏览器;
//浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示;

  回顾一下socket的udp连接和tcp连接,注:查看当前进程和杀死进程的window命令:

    netstat -ano|findstr 45678

    taskkill -PID 45678的进程 -F

  udp客户端和服务端

import socket
# upd链接
# SOCK_DGRAM:数据报套接字,主要用于UDP协议
udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 关闭防火墙
# 同一网段(局域网)下,主机的ip地址和端口号.
sendAddr = ('192.168.10.247', 8080) # 绑定端口:写的是自己的ip和固定的端口,一般是写在sever端.
udpSocket.bind(('', 9900)) # sendData = bytes(input('请输入要发送的数据:'), 'gbk')
# gbk, utf8, str
sendData = input('请输入要发送的数据:').encode('gbk') # python3是unicode编码,也就是以unicode格式写成的字节.
# encode,重写编码:就是把unicode环境下的数据,重新编码成指定格式的字节,比如gbk, utf8等.然后接收方以同样的解码格式解码.
# 用网络串口助手作为udp的服务端.网络串口助手是字节和十六进制的字节,没有unicode编码,有gbk编码和utf8编码.所以要解码成gbk
# 反过来,接收数据的时候,也要知道对方发送的数据要怎么解码. # 使用udp发送数据,每一次发送都需要写上接收方的ip地址和端口号
udpSocket.sendto(sendData, sendAddr)
# udpSocket.sendto(b'hahahaha', ('192.168.10.247', 8080)) udpSocket.close()

udp客户端

import socket

udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 接收方一般需要绑定端口
# ''表示自己电脑的任何一个ip,即无线和有限同时连接或者电脑有不同的网卡(桥接),会有多个ip.
# 绑定自己的端口
bindAddr = ('', 7788)
udpSocket.bind(bindAddr) recvData = udpSocket.recvfrom(1024)
# print(recvData)
print(recvData[0].decode('gbk')) udpSocket.close()
# recvData的格式:(data, ('ip', 端口)).它是一个元组,前面是数据,后面是一个包含ip和端口的元组.

udp服务端

  tcp客户端和服务端

import socket

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

serverAddr = ('192.168.10.247', 8899)

# tcp的三次握手,写进了这一句话
tcpClient.connect(serverAddr) sendData = input('') # 直接用send就行了,udp是用sendto
tcpClient.send(sendData.encode('gbk')) recvData = tcpClient.recv(1024) print('接收到的数据为:%s' % recvData.decode('gbk')) tcpClient.close() # 为什么用send而不是sendto?因为tcp连接是事先链接好了,后面就直接发就行了。前面的connect已经连接好了,后面直接用send发送即可。
# 而udp必须用sendto,是发一次数据,连接一次。必须要指定对方的ip和port。
# 相同的道理,在tcpServer端,要写recv,而不是recvfrom来接收数据

tcp客户端

import socket
tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServer.bind(('', 8899))
tcpServer.listen(5) # tcp的三次握手,写进了这一句话当中
tcpClient, tcpClientInfo = tcpServer.accept()
# tcpServer.accept(),不需要写ip,可以接收多个客户端的。但事先要绑定端口和接入的客户端的数量
# client 表示接入的新的客户端
# clientInfo 表示接入的新的客户端的ip和端口port recvData = tcpClient.recv(1024)
print('%s: %s' % (str(tcpClientInfo), recvData.decode('gbk'))) # tcp的四次握手,写进了这一句话
tcpClient.close()
tcpServer.close() # tcpServer.accept():等待客户端的接入,自带堵塞功能:即必须接入客户端,然后往下执行
# tcpClient.recv(1024): 也是堵塞,不输入数据就一直等待,不往下执行.
# tcpServer创建了两个套接字,一个是Server,另一个是tcpClient.Server负责监听接入的Client,再为其创建专门的tcpClient进行通信.

tcp服务端

  两个小实例:tcpServer开启循环模式,以及udp的多线程聊天室

import socket

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

Server.bind(('', 9000))
Server.listen(10) while True:
# 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务
serverThisClient, ClientInfo = Server.accept()
print('Waiting connect......') # 如果客户发送的数据是空的,那么断开连接
while True:
recvData = serverThisClient.recv(1024)
if len(recvData) > 1: print('recv: %s' % recvData.decode('gbk')) sendData = input('send: ')
serverThisClient.send(sendData.encode('gbk'))
else:
print('再见!')
break
serverThisClient.close()

开启循环模式

from threading import Thread
import socket
# 收数据,然后打印
def recvData():
while True:
recvInfo = udpSocket.recvfrom(1024)
print('%s:%s' % (str(recvInfo[1]), recvInfo[0].decode('gbk'))) # 检测键盘,发数据
def sendData():
while True:
sendInfo = input('')
udpSocket.sendto(sendInfo.encode('gbk'), (destIp, destPort)) udpSocket = None
destIp = ''
destPort = 0
# 多线程
def main(): global udpSocket
global destIp
global destPort destIp = input('对方的ip: ')
destPort = int(input('对方的端口:')) udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udpSocket.bind(('', 45678)) tr = Thread(target=recvData)
ts = Thread(target=sendData) tr.start()
ts.start() tr.join()
ts.join()
if __name__ == '__main__':
main()

多线程聊天室

  根据以上socket,可以写一个简单的web应用

import socket

def handle_request(client):
buf = client.recv(1024) # 请求头
print(buf.decode('utf8'))
client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8")) # 响应头
client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8")) # body数据
# 把上面的html写到当前文件夹下的html里,把上行代码换成下面代码,就是一个web基本的流程.
# with open('hello.html', 'rb') as f:
# data = f.read()
# client.send(data) def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost',8001))
sock.listen(5) while True:
connection, address = sock.accept()
handle_request(connection)
connection.close() if __name__ == '__main__':
main() # 在浏览器中输入localhost:8001,显示红色字体的hello,yuan.
# 在后台Terminal中,会输出buf的内容:
'''
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, image/jxr, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063
Accept-Encoding: gzip, deflate
Host: 127.0.0.1:8001
Connection: Keep-Alive
Cookie: csrftoken=pW12OxqURLh8VgHwwR1TzlR65ubxDzZgBv9SJtXZZeKuqd38TWGyntT84gX29rtr
'''

最简单的web小程序

二、WSGI

  接收HTTP请求,解析HTTP请求,发送HTTP响应(如上面显示的)涉及到TCP连接、HTTP原始请求和响应格式。它涉及到底层较为复杂的构造:

  根据网络通信的OSI模型,应用层封装一次数据,包含http参数和数据(数据格式是HTML,CSS,协议是TLS、HTTP等),然后发给传输层;

  传输层接收封装后的数据,再封装一次,加上tcp头,变成tcp头、http data, 然后发给网络层;

  网络层接收封装后的数据,再封装一次,加上ip头,变成ip头、tcp头、http data,然后发给数据数据链路层;

  数据链路层接收封装后的数据,再封装一次,加上以太网头,变成ethernet头、ip头、tcp头、 http data,通过物理层对客户端浏览器进行响应。

  这样,web服务端算是完成了一次响应。【详见OSI模型】

  python内置了一个WSGI服务器(Web Server Gateway Interface),这个模块就是wigiref。它封装了对tcp、http请求和响应的操作。它负责处理socket的接口(封装了socket对象和准备过程(bind,listen等)),把请求信息(请求头和请求体)封装成键值对的对象,并可以方便地设置响应头和返回请求体。下面通过一个wsgi内置的写一个 web应用来加深理解wsg。i

  step1:WSGI的environ和return

from wsgiref.simple_server import make_server

def application(environ, start_response):
for key, value in environ.items():
print(key, value)
# 响应头,告诉浏览器响应的内容是什么格式
start_response('200 OK', [('Content-Type', 'text/html')])
return [b'<h1>Hello, web!</h1>'] # 响应体 # make_server是一个http对象
httpd = make_server('', 8080, application)
print('Serving HTTP on port 8000 ...') # 开始监听HTTP请求:
httpd.serve_forever() '''
application()就是符合wSGI标准的一个HTTP处理函数,它接收两个参数:
environ:一个包含所有HTTP请求信息的dict对象;
start_response:一个发送HTTP响应的函数;
在applicaiton()函数中调用start_response('200 OK', [('Content-Type', 'text/html')]),就发送了HTTP响应的Header.
start_response()函数接收两个参数:
一个是HTTP响应码
一个是一组list表示的HTTP Header,每个Header用一个包含两个str的tuple表示.
通常会把Content-Type头发送给浏览器,其他很多常用的HTTP Header也应该发送。
然后,函数的返回值b'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器.
有了WSGI,我们关心的就是如何从environ中拿到解析好的请求信息,从而写自己的处理逻辑了。
'''

WSGI的simple_server

ALLUSERSPROFILE C:\ProgramData
APPDATA C:\Users\admin\AppData\Roaming
COMMONPROGRAMFILES C:\Program Files\Common Files
COMMONPROGRAMFILES(X86) C:\Program Files (x86)\Common Files
COMMONPROGRAMW6432 C:\Program Files\Common Files
COMPUTERNAME DESKTOP-ABISCDM
COMSPEC C:\WINDOWS\system32\cmd.exe
FPS_BROWSER_APP_PROFILE_STRING Internet Explorer
FPS_BROWSER_USER_PROFILE_STRING Default
HOMEDRIVE C:
HOMEPATH \Users\admin
LOCALAPPDATA C:\Users\admin\AppData\Local
LOGONSERVER \\DESKTOP-ABISCDM
MOZ_PLUGIN_PATH C:\其它软件\福昕阅读器\Foxit Reader\plugins\
NUMBER_OF_PROCESSORS 4
ONEDRIVE C:\Users\admin\OneDrive
OS Windows_NT
PATH C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\;C:\Program Files\MySQL\MySQL Utilities 1.6\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Zpythons\python36\Scripts\;C:\Zpythons\python36\;C:\Users\admin\AppData\Local\Microsoft\WindowsApps;
PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PROCESSOR_ARCHITECTURE AMD64
PROCESSOR_IDENTIFIER Intel64 Family 6 Model 142 Stepping 9, GenuineIntel
PROCESSOR_LEVEL 6
PROCESSOR_REVISION 8e09
PROGRAMDATA C:\ProgramData
PROGRAMFILES C:\Program Files
PROGRAMFILES(X86) C:\Program Files (x86)
PROGRAMW6432 C:\Program Files
PSMODULEPATH C:\Program Files\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules
PT5HOME C:\Cisco Packet Tracer 6.0
PT6HOME C:\Cisco Packet Tracer 6.0
PUBLIC C:\Users\Public
PYCHARM_HOSTED 1
PYTHONIOENCODING UTF-8
PYTHONPATH C:\Users\admin\Desktop\pythonNote\网络编程基础
PYTHONUNBUFFERED 1
SESSIONNAME Console
SYSTEMDRIVE C:
SYSTEMROOT C:\WINDOWS
TEMP C:\Users\admin\AppData\Local\Temp
TMP C:\Users\admin\AppData\Local\Temp
USERDOMAIN DESKTOP-ABISCDM
USERDOMAIN_ROAMINGPROFILE DESKTOP-ABISCDM
USERNAME admin
USERPROFILE C:\Users\admin
VS140COMNTOOLS C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\
WINDIR C:\WINDOWS
SERVER_NAME DESKTOP-ABISCDM
GATEWAY_INTERFACE CGI/1.1
SERVER_PORT 8080
REMOTE_HOST
CONTENT_LENGTH
SCRIPT_NAME
SERVER_PROTOCOL HTTP/1.1
SERVER_SOFTWARE WSGIServer/0.2
REQUEST_METHOD GET
PATH_INFO /alex
QUERY_STRING
REMOTE_ADDR 127.0.0.1
CONTENT_TYPE text/plain
HTTP_HOST 127.0.0.1:8080
HTTP_USER_AGENT Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_LANGUAGE zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
HTTP_ACCEPT_ENCODING gzip, deflate
HTTP_COOKIE csrftoken=b2CBBrcSjnRT91jAB1KJzUWphnWB28UiLrHQuECAsv6vWPy4vGWIsHXkRHWh0gTy; sessionid=y4l1ybo6t01nhpqsjkh6fyqm44blinca
HTTP_CONNECTION keep-alive
HTTP_UPGRADE_INSECURE_REQUESTS 1
HTTP_CACHE_CONTROL max-age=0
wsgi.input <_io.BufferedReader name=748>
wsgi.errors <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>
wsgi.version (1, 0)
wsgi.run_once False
wsgi.url_scheme http
wsgi.multithread True
wsgi.multiprocess False
wsgi.file_wrapper <class 'wsgiref.util.FileWrapper'>

查看environ封装的所有信息

  step2:根据浏览器输入的url,进行逻辑处理:

from wsgiref.simple_server import make_server

def application(environ, start_response):

    # 响应头,告诉浏览器响应的内容是什么格式
start_response('200 OK', [('Content-Type', 'text/html')])
# message = start_response('200 OK', [('Content-Type', 'text/html')])
# print(message) # 打印所有的请求信息
for key, value in environ.items():
print(key, value) # 从environ中拿到url,键名是'PATH_INFO',然后做一个处理:
path = environ['PATH_INFO']
f1 = open('index1.html', 'rb')
data1 = f1.read() #当前文件夹下创建index1.html和index2.html,内容随便写.
f2 = open('index2.html', 'rb')
data2 = f2.read()
if path == '/yuan':
return [data1]
elif path == '/alex':
return [data2]
else:
return [b'<h1>Hello, web!</h1>'] # 响应体 # make_server是一个http对象
httpd = make_server('', 8080, application)
print('Serving HTTP on port 8000 ...') # 开始监听HTTP请求:
httpd.serve_forever()

接收请求并进行逻辑处理

  step3:把上述逻辑处理进行解耦:

from wsgiref.simple_server import make_server

def f1():
f1 = open('index1.html', 'rb')
return [f1.read()]
def f2():
f2 = open('index2.html', 'rb')
return [f2.read()] def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
path = environ['PATH_INFO'] if path == '/yuan':
return f1()
elif path == '/alex':
return f2()
else:
return [b'<h1>Hello, web!</h1>'] httpd = make_server('', 8080, application)
print('Serving HTTP on port 8000 ...') httpd.serve_forever()

解耦式写法

  step4:接近MVC的升级式写法:

import time
from wsgiref.simple_server import make_server def f1(request):
print(request['QUERY_STRING'])
f1 = open('index1.html', 'rb')
return [f1.read()] def f2(request):
f2 = open('index2.html', 'rb')
return [f2.read()] def f3(request):
f3 = open('index3.html', 'rb')
localtime = time.strftime('%Y-%m-%d %X',time.localtime())
html = f3.read()
print(html)
html = str(html, 'utf8').replace('!time!', str(localtime))
return [html.encode('utf8')] def routes():
urlpatterns = [
('/yuan', f1),
('/alex', f2),
('/cur_time', f3),
]
return urlpatterns def application(environ, start_response):
path = environ['PATH_INFO']
start_response('200 OK', [('Contentt-Type', 'text/html')]) urlpatterns = routes()
func = None
for item in urlpatterns:
if item[0] == path:
func = item[1]
break if func:
return func(environ)
else:
return ['<h2>404</h2>'.encode('utf8')] httpd = make_server('', 8001, application)
print('Serving HTTP on port 8001 ...') httpd.serve_forever() # 在浏览器中输入localhost:8001/yuan,或/alex,或/cur_time,或一个不存在的url地址 '''
html=b'<!DOCTYPE html>\r\n<html lang="en">\r\n<head>\r\n <meta charset="UTF-8">\r\n <title>Title</title>\r\n</head>\r\n<body>\r\n<h2>!time!</h2>\r\n</body>\r\n</html>'
要点一:
f3中的html,只写了个h2标签,里面写了!time!这个单词。
f3跟f1,f2的不同之处在于,它对html进行了修改操作(访问一次,打印一次当前时间戳)。
假如定义!time!是一个固定的“语言”,像!vector!,!func!等,都作为“自定义”的python处理方式,那么就可以识别该操作符,然后进行处理。
django定义{{ 变量/函数 }} 和{% 变量/函数/简单循环 %},来与html进行交互。 它扩展为django中的render功能,能够支持对html文件传入参数。以及templatetags,用来在后端给html增加一些功能。 要点二:
rountes函数:在list列表中存放每个url和相应的处理函数的tuple,绑定url和处理函数。
每当有url访问,就对这个List对象进行遍历,找到处理函数就返回相应的结果,没找到就返回一个404错误。
它相当于django中的url.py文件。 applicattion()函数中写了多行代码来处理url和func的映射关系。
在django中,它被封装了起来, 用户只需要在urlpatterns中添加url和处理函数。然后在views中写处理逻辑就行了。 '''

升级版写法

  如果把f1(),f2(),f3()写在一个models.py中,把routes写进一个urls.py中,把application写在controller.py中,把html写在一个view文件夹下。那就构成了web框架中著名的MVC模式。

三、web框架的MVC模式和django的MTV模式

  大部分开发语言中都有MVC框架,MVC框架的核心思想是:解耦。上面WSGI的升级版写法已经体现了这个特点。

  

  所谓MVC,就是指model、view、controller。m主要用于对数据库层的封装,v主要向用户展示结果,c是核心,用于处理请求、获取数据、返回结果。

  django是一款python的web开发框架,使用了MVT模式,它本质上与MVC模式没什么差别。MVT是model, template, view。m负责业务对象与数据库的对象(ORM), template负责如何把页面展示给用户,view负责业务逻辑,并在适当的时候调用model和template。此外,还有一个url分发器,它的作用是将一个个url页面请求分发给不同的view处理。

  重新解释一遍:model负责与数据库交互,view是核心,负责接收请求,获取数据,返回结果,template负责呈现内容到浏览器。

http://www.cnblogs.com/yuanchenqi/articles/6083427.html
# 老男孩python全栈工程师培训著名讲师苑昊博客

原文链接地址

django基础一:web、wsgi、mvc、mtv的更多相关文章

  1. Django WSGI,MVC,MTV,中间件部分,Form初识

    一.什么是WSGI? WEB框架的本质是一个socket服务端接收用户请求,加工数据返回给客户端(Django),但是Django没有自带socket需要使用 别人的 socket配合Django才能 ...

  2. python web框架 MVC MTV

    WEB框架 MVC Model View Controller 数据库 模板文件 业务处理 MTV Model Template View 数据库 模板文件 业务处理

  3. python django基础一web框架的本质

    web框架的本质就是一个socket服务端,而浏览器就是一个socker客户端,基于请求做出相应,客户端先请求,服务器做出对应响应 按照http协议的请求发送,服务器按照http协议来相应,这样的通信 ...

  4. Django基础一Web框架的本质

    我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端,基于请求做出响应,客户都先请求,服务端做出对应的响应,按照http协议的请求协议发送请求, ...

  5. Django基础一

    Django基础一 Web框架本质 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演 ...

  6. Django之WSGI 和MVC/MTV

    一.什么是WSGI? WEB框架的本质是一个socket服务端接收用户请求,加工数据返回给客户端(Django),但是Django没有自带socket需要使用 别人的 socket配合Django才能 ...

  7. Django基础之MTV模型

    一.Django基础 一.Django简介 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的软件设计模式,即模型(Model).视图(View)和控制器(Control ...

  8. python笔记-19 javascript补充、web框架、django基础

    一.JavaScript的补充 1 正则表达式 1.1 test的使用 test 测试是否符合条件 返回true or false 1.2 exec的使用 exec 从字符串中截取匹配的字符 1.3 ...

  9. day 52 Django基础一之web框架的本质

    Django基础一之web框架的本质   django第一天 本节目录 一 web框架的本质及自定义web框架 二 模板渲染JinJa2 三 MVC和MTV框架 四 Django的下载安装 五 基于D ...

随机推荐

  1. 将整个文件读入string中

    size_t GetFileSize(FILE* file) { fseek(file, , SEEK_END); return static_cast<size_t>(ftell(fil ...

  2. CSS单行超长溢出如何处理?表格某一行某一列超长如何处理?

    表格某一行某一列超长 截取一部分 并增加...效果 增加titile ======================================================== <td t ...

  3. mysqli扩展库---事务控制

    1, 有一张银行账号表 create table account( id int primary key, balance float ); 2,现在有一段php程序,要完成把1号10元钱,转到2号账 ...

  4. jquery源码解析:jQuery静态属性对象support详解

    jQuery.support是用功能检测的方法来检测浏览器是否支持某些功能.针对jQuery内部使用. 我们先来看一些源码: jQuery.support = (function( support ) ...

  5. 8,Phaser__并发且多阶段任务

    使用场景 考选武状元 10 个 武生 参加考试 ,第一个关 靠耐力, 坚持最久的5个人进入第二关, 第二关考 力气,力气最大的 3个人进入第二关,第三关考兵法,兵法最好的当选武状元

  6. leetcode-680-Valid Palindrome II

    题目描述: Given a non-empty string s, you may delete at most one character. Judge whether you can make i ...

  7. 题目1018:统计同成绩学生人数(hash简单应用)

    问题来源 http://ac.jobdu.com/problem.php?pid=1018 问题描述 给你n位同学的成绩,问获得某一成绩的学生有多少位. 问题分析 初见此题,有人会想到先将所有成绩存入 ...

  8. 【算法笔记】B1033 旧键盘打字

    1033 旧键盘打字 (20 分) 旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及坏掉的那些键,打出的结果文字会是怎样? 输入格式: 输入在 2 行 ...

  9. Flask基础应用

    一. Python 现阶段三大主流Web框架 Django Tornado Flask 对比 Django: 优点: 大而全,组件非常全面. 缺点: 太大,加载太大,浪费资源. Flask: 优点: ...

  10. mAP(mean Average Precision)应用(转)

    原文章地址来自于知乎:https://www.zhihu.com/question/41540197 1. precision 和 recall 的计算(没什么好说的,图片示例相当棒): 图1 图中上 ...