python之闭包以及服务器的开发

发布于:2024-06-29 ⋅ 阅读:(18) ⋅ 点赞:(0)

闭包: 函数嵌套函数 函数的返回值是一个函数  内部函数使用了外部函数的变量 造成数据不会被释放。

函数的参数是一个变量

def f(a):
    def f1():
        print(a)
    return f1

f2 = f(2)
f2() # 2 

函数的参数是另外一个函数

def fn(f):
    def fn1():
        f()
    return fn1

def a():
    print('111')

s = fn(a)
s1 = s()
print(s1)

内部函数无法直接修改外部函数的变量

def a():
    num = 10
    def b():
        num = 20
        print(num)
    print(num)
    b()
    print(num)

a() # 10 20 10 内部函数无法直接修改外部函数的变量 

内部函数如果想要修改外部函数的变量值 需要使用关键字 nonlocal 

def a():
    num = 20
    def b():
        nonlocal num
        num = 30
        print(num)
    print(num)
    b()
    print(num)

a() # 20 30 30

定义装饰器,相当于是下面的函数直接作为参数传递给闭包的函数

def fn(callback):
    print('我是外部的函数')
    def fn1():
        print('我是内部的函数')
        callback()
    return fn1

@fn   # 使用装饰器
def callback():
    print('我是参数的函数啊')

callback()

闭包的参数是一个函数 该函数内部还接受参数:

def f(call):
    num = 10
    def b(a,b):
        c = call(a,b)
        print(c+num) # 30 
        return c+num
    return b

@f
def call(a,b):
    return a+b

call(10,10)

多个执行器的使用:

def a(call):
    def b():
        num = call()
        return num+1
    return b


def c(call):
    def d():
        num = call()
        return num+2
    return d

@a
@c
def call():
    return 10

e =call()
print(e) # 13  先执行@c的这个装饰器将最后的结果 再给到@a的执行器再去执行 

带有参数的装饰器

def func(flag):
    def fn(call):
        def b(a,b):
            if flag == '+':
                print('执行加法')
            elif flag == '-':
                print('执行减法')
            num = call(a,b)
            print(num)
        return b
    return fn

@func("+")
def add(a,b):
    return a+b

@func("-")
def cl(a,b):
    return a-b

g = add(10,20)

h = cl(20,10)

使用类装饰器:

class Students(object):
    def __init__(self,fun):
        self.fun=fun

    def __call__(self, *args, **kwargs):
        print('调用函数')
        self.fun()

@Students
def fn():
    print('我是被调用的函数')
# 调用函数   我是被调用的函数
fn() # 当函数被调用的时候 会执行 类中的__call__的这个方法 同时fn本身的这个函数也会被调用

web服务 框架开发:

import socket
import framewprk
# 创建服务器 ipv地址 tcp链接
tcp_server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 设置端口号复用
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
# 绑定端口号
tcp_server_socket.bind(('',8000))
# 设置监听
tcp_server_socket.listen(128)
# 循环等待客户端链接
while True:
    #建立链接后 获取的客户端的内容 new_socket为二进制   ip_prot=127.0.0.1 还有链接的号码
    new_socket,ip_prot = tcp_server_socket.accept()

    recv_data=new_socket.recv(4096)

    print(recv_data)
    print(len(recv_data)) # 长度725 每次都不固定

    if len(recv_data) != 0: # 说明有建立链接

        recv_content = recv_data.decode('utf-8')

        print(recv_content)  # 转化成了 请求报文的格式了

        quest_path = recv_content.split(' ',2)[1]

        print(quest_path) # / 或者 /index.html

        if quest_path == '/':
            quest_path = '/index.html'

        if quest_path.endswith('.html'):

            env = {"request_path":quest_path}
            # 调用外部的框架来处理动态资源的请求
            status,headers,response_body = framewprk.handle_request(env)

            print(status,headers,response_body)

            # 响应行
            response_line = "HTTP/1.1 %s\r\n" %status
            # 响应头
            response_header = ""
            for header in headers:
                response_header+="%s:%s\r\n" % header
            # 响应报文
            response_data = (response_line+response_header+"\r\n"+response_body).encode('utf-8')
            print(response_data)
            # 发送给浏览器
            new_socket.send(response_data)
            # 关闭链接
            new_socket.close()
        else:
            try:
                with open('./'+quest_path,'rb') as file:
                    file.read()
            except Exception as e:
                with open("error.html", 'rb') as file:
                    file_data = file.read()
                    # 设置响应行
                    response_line = 'HTTP/1.1 200 OK\r\n'
                    # 设置响应头
                    response_header = "Server:PWS/1.0\r\n"
                    # 响应体
                    response_body = file_data
                    # 进行拼接 转化为二进制
                    response = (response_line + response_header + "\r\n").encode('utf-8') + response_body
                    # 给客户端响应消息
                    new_socket.send(response)
            else:
                # 设置响应行
                response_line = 'HTTP/1.1 200 OK\r\n'
                # 设置响应头
                response_header = "Server:PWS/1.0\r\n"
                # 响应体
                response_body = file_data
                # 进行拼接 转化为二进制
                response = (response_line + response_header + "\r\n").encode('utf-8') + response_body
                # 给客户端响应消息
                new_socket.send(response)
            finally:
                # 关闭链接
                new_socket.close()

Framewprk文件中的代码:
import time

#获取首页的数据
def index():
    status="200 ok"
    response_header = [("Server","PWS/1.1")]
    # 返回死的数据 也就是返回当前的时间
    # data = time.ctime()
    # 这里是返回首页index的内容
    with open('index.html','r',encoding='utf-8') as file:        file_data = file.read()

    data = time.ctime()

    request_body=file_data.replace('{%content%}',data)

    return status,response_header,request_body

def center():
    pass

# 处理没有找到动态路径
def not_found():
    status = '404 Not Found'
    response_header = [("Server", "PWS/1.1")]
    data = "not Found"
    return status,response_header,data


# 定义路由表
router_list = [('/index.html',index),('/center.html',center)]

# 处理路由的函数
def handle_request(env):
    request_path = env['request_path']
    # if request_path == '/index.html':
    #     return index()
    # else:
    #     return not_found()

    # 上面的代码修改为下面的  key:index.htmll  fun:index()
    for key,fun in router_list:
        if key == request_path:
            return fun()
    else:
        return not_found()

使用装饰器来开发web框架:

import time

router_list=[]

#装饰器处理路由的问题 
def router(path):
    def decorator(call):
        # 把对应的路由给添加进去
        router_list.append((path,call)) # ('/index.html',index)
        def fn():
            return call()
        return fn
    return decorator


# 处理没有找到动态路径
def not_found():
    status = '404 Not Found'
    response_header = [("Server", "PWS/1.1")]
    data = "not Found"
    return status,response_header,data


@router('/index.html')
def index():
    def index():
        status = "200 ok"
        response_header = [("Server", "PWS/1.1")]
        # 返回死的数据 也就是返回当前的时间
        # data = time.ctime()
        # 这里是返回首页index的内容
        with open('index.html', 'r', encoding='utf-8') as file:
            file_data = file.read()

        data = time.ctime()

        request_body = file_data.replace('{%content%}', data)

        return status, response_header, request_body

# 处理路由的函数
def handle_request(env):
    request_path = env['request_path']
    for key,fun in router_list:
        if key == request_path:
            return fun()
    else:
        return not_found()

给客户端返回JSON格式的字符串 并且数据是从mysql数据库中获取的

import time
import pymysql
import json


#获取首页的数据
def index():
    status="200 ok"
    response_header = [("Server","PWS/1.1")]
    # 返回死的数据 也就是返回当前的时间
    # data = time.ctime()
    # 这里是返回首页index的内容
    with open('index.html','r',encoding='utf-8') as file:
        file_data = file.read()

        data = time.ctime()

    request_body=file_data.replace('{%content%}',data)

    return status,response_header,request_body

def center():
    conn = pymysql.connect(host="localhost",port=3306,user="root",password="123456",database="test",charset="utf8")
    cursor = conn.cursor()
    sql = """select * from user;"""
    cursor.execute(sql)
    result = cursor.fetchall()  # ((2, 'zs'), (3, 'hs'), (4, 'wq'))
    center_data_list=[{"id": row[0], "name": row[1]} for row in result]
    json_str = json.dumps(center_data_list)
    cursor.close()
    conn.close()
    status = "200 OK"
    response_header = [("server","pws/1.1")]
    return status,response_header,json_str



# 处理没有找到动态路径
def not_found():
    status = '404 Not Found'
    response_header = [("Server", "PWS/1.1")]
    data = "not Found"
    return status,response_header,data


# 定义路由表
router_list = [('/index.html',index),('/center.html',center)]

# 处理路由的函数
def handle_request(env):
    request_path = env['request_path']
    # if request_path == '/index.html':
    #     return index()
    # else:
    #     return not_found()

    # 上面的代码修改为下面的  key:index.htmll  fun:index()
    for key,fun in router_list:
        if key == request_path:
            return fun()
    else:
        return not_found()