阅读flask源码3:仿写Local,LocalStack

2024-03-16 22:08

本文主要是介绍阅读flask源码3:仿写Local,LocalStack,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们上篇分析了上下文压入栈,出栈的大致流程,现在我们要问,flask是怎么实现的呢?准备来说,Local是怎么管理不同请求对象的,LocalProxy是怎么代理的。因为flask源码太复杂,今天我们自己一步一步实现类似于Local,LocalProxy的代码。通过自己实现,我们学会用代理模式,学会python的魔法方法__setattr__,getattr

class A(object):def spam(self, x):print('A.spam')def foo(self):print('A.foo')# 简单的代理
class AProxy(object):def __init__(self):self._a = A()def spam(self,x):print('B1.spam')return self._a.spam(x)def foo(self):print('B1.foo')return self._a.foo()def bar(self):print('B1.bar')b1 = AProxy()
b1.spam(1)
b1.foo()
b1.bar()

这里的b1,是一个对象,我们访问b1.spam(1),它会返回类A的一个实例的方法。b1.foo()也同理。

这个代理的问题是,我们写代理的时候,要先知道被代理的类A有哪些方法,下面我们实现一种更通用的代理。

class A(object):def spam(self, x):print('A.spam')def foo(self):print('A.foo')# 简单的代理
class AProxy(object):def __init__(self):self._a = A()self.name = ''def __getattr__(self,name):return getattr(self._a,key)def bar(self):print('B1.bar')b1 = AProxy()
b1.spam(1)
b1.foo()
b1.bar()

上面这个代理,比第一个就抽象了,这晨用__getattr__实现了什么呢?只要你访问AProxy没有的方法,它就会去__getattr__中找,这个函数实现了你给一个函数名,它会给你被代理对象的函数。这里是一个抽象。

上面这个函数,只是实现了属性,方法的访问,却不能给它赋值。

class A(object):def __init__(self):self.log = ''def spam(self, x):print('A.spam')def foo(self):print('A.foo')# 简单的代理
class AProxy(object):def __init__(self):self._a = A()self.name = ''def __getattr__(self,name):return getattr(self._a,key)def __setattr__(self,name,value):return setattr(self._a,name,value)def bar(self):print('B1.bar')b1 = AProxy()
b1.name = '我是AProxy的一个实例'
b1.log = '我是A的一个实例'

这个代理就比前一个更好用了,因为它可以给A的实例间接赋值。我们调用b1.log,这个时候AProxy没有这个属性,这时就去__setattr__中找,把log,'我是A的一个实例’作为实参,传给__setattr__。

当然这个代理也有些问题,就是它还不够抽象,它现在只能代理类A,如果我们希望它还能代理其它类怎么办呢?

改进如下:

class A(object):def __init__(self):self.log = ''def spam(self, x):print('A.spam')def foo(self):print('A.foo')# 简单的代理
class AProxy(object):def __init__(self,object):self._a = objectself.name = ''def __getattr__(self,name):return getattr(self._a,key)def __setattr__(self,name,value):return setattr(self._a,name,value)def bar(self):print('B1.bar')
a1 = A
b1 = AProxy(a1)
b1.name = '我是AProxy的一个实例'
b1.log = '我是A的一个实例'

这里通过一个给AProxy传参初始化,可以拿到不同的实例代理。

有了上面这些基础,现在我们模仿Local,LocalProxy来写一个代理:

class Request(object):def __init__(self):self.url = 'tanliang.com'class User(object):def __init__(self):self.owner = 'tanliang'class Local:def __init__(self):self._objs = {}self._objs['request'] = Request()self._objs['user'] = User()def __getattr__(self, name):print('Local.__getattr__')return self._objs[name]def __call__(self, name):return LocalProxy(self, name)class LocalProxy(object):def __init__(self, local, name):self._local = localself._name = namedef _get_current_obj(self):print('_get_current_obj')return getattr(self._local, self._name)def __getattr__(self, name):print('SpamProxy.__getattr__')return getattr(self._get_current_obj(), name)def __setattr__(self, name ,value):if name.startswith('_'):super().__setattr__(name, value)else:setattr(self._obj, name, value)def __delattr__(self, name):print('SpamProxy.__delattr__')if name.startswith('_'):super().__delattr__(name)else:print('SpamProxy', name)delattr(self._obj, name)l = Local()request = l('request')
print(request)
print(request.url)user = l('user') 
print(user.owner)

这里l是一个Local实例,request是一个代理对象,LocalProxy的实例,因为Local实现了__call__方法。当我们访问request.url时,会发生什么呢?先找到__getattr__,然后把url作为参数传给getattr。可是这个时候还没有拿到“当前对象”。self.__get_current_obj()就是拿当前对象的,最后能过Local的__getattr__拿到request对象。

这篇关于阅读flask源码3:仿写Local,LocalStack的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/816865

相关文章

java 恺撒加密/解密实现原理(附带源码)

《java恺撒加密/解密实现原理(附带源码)》本文介绍Java实现恺撒加密与解密,通过固定位移量对字母进行循环替换,保留大小写及非字母字符,由于其实现简单、易于理解,恺撒加密常被用作学习加密算法的入... 目录Java 恺撒加密/解密实现1. 项目背景与介绍2. 相关知识2.1 恺撒加密算法原理2.2 Ja

Nginx屏蔽服务器名称与版本信息方式(源码级修改)

《Nginx屏蔽服务器名称与版本信息方式(源码级修改)》本文详解如何通过源码修改Nginx1.25.4,移除Server响应头中的服务类型和版本信息,以增强安全性,需重新配置、编译、安装,升级时需重复... 目录一、背景与目的二、适用版本三、操作步骤修改源码文件四、后续操作提示五、注意事项六、总结一、背景与

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

Python Flask实现定时任务的不同方法详解

《PythonFlask实现定时任务的不同方法详解》在Flask中实现定时任务,最常用的方法是使用APScheduler库,本文将提供一个完整的解决方案,有需要的小伙伴可以跟随小编一起学习一下... 目录完js整实现方案代码解释1. 依赖安装2. 核心组件3. 任务类型4. 任务管理5. 持久化存储生产环境

Python用Flask封装API及调用详解

《Python用Flask封装API及调用详解》本文介绍Flask的优势(轻量、灵活、易扩展),对比GET/POST表单/JSON请求方式,涵盖错误处理、开发建议及生产环境部署注意事项... 目录一、Flask的优势一、基础设置二、GET请求方式服务端代码客户端调用三、POST表单方式服务端代码客户端调用四

flask库中sessions.py的使用小结

《flask库中sessions.py的使用小结》在Flask中Session是一种用于在不同请求之间存储用户数据的机制,Session默认是基于客户端Cookie的,但数据会经过加密签名,防止篡改,... 目录1. Flask Session 的基本使用(1) 启用 Session(2) 存储和读取 Se

Python Web框架Flask、Streamlit、FastAPI示例详解

《PythonWeb框架Flask、Streamlit、FastAPI示例详解》本文对比分析了Flask、Streamlit和FastAPI三大PythonWeb框架:Flask轻量灵活适合传统应用... 目录概述Flask详解Flask简介安装和基础配置核心概念路由和视图模板系统数据库集成实际示例Stre

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

python web 开发之Flask中间件与请求处理钩子的最佳实践

《pythonweb开发之Flask中间件与请求处理钩子的最佳实践》Flask作为轻量级Web框架,提供了灵活的请求处理机制,中间件和请求钩子允许开发者在请求处理的不同阶段插入自定义逻辑,实现诸如... 目录Flask中间件与请求处理钩子完全指南1. 引言2. 请求处理生命周期概述3. 请求钩子详解3.1

Python Flask 库及应用场景

《PythonFlask库及应用场景》Flask是Python生态中​轻量级且高度灵活的Web开发框架,基于WerkzeugWSGI工具库和Jinja2模板引擎构建,下面给大家介绍PythonFl... 目录一、Flask 库简介二、核心组件与架构三、常用函数与核心操作 ​1. 基础应用搭建​2. 路由与参