flask基础之LocalProxy代理对象(八)

本文深入探讨了Flask框架中的代理对象概念,包括request, session, g和current_app,解释了代理模式如何解决循环导入问题,以及LocalProxy如何在Werkzeug工具中实现动态代理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

flask框架自带的代理对象有四个,分别是request,session,g和current_app,各自的含义我们在前面已经详细分析过。使用代理而不是显式的对象的主要目的在于这四个对象使用太过频繁,贯穿整个请求周期,显式传递很容易造成循环导入的问题,需要一个第三方的对象来进行解耦。

代理模式简介

代理模式是程序设计的一种结构模式,其目的是使调用者和执行者之间不发生直接的关系,而是使用一个代理人,这样调用者和执行者就进行了解耦,可以避免许多的问题。

代理模式使用的场景:

  • 为真实目标类创建一个对象的代价是昂贵的,而创建代理类很简单;

  • 对象必须防止被用户直接使用。

  • 当实际请求的时候,为真实目标类创建一个对象会有延迟。

class Boss(object):
    def task1(self):
        print('this is task1')
    def task2(self):
        print('this is task2')

class Proxy(object):
    def __init__(self, obj):
        self.proxy = obj
    def task1(self):
        self.proxy.task1()
    def task2(self):
        self.proxy.task2()

proxy_boss = Proxy(Boss())

class Client(object):
    def do_something(self):
        proxy_boss.task1()
if __name__ == '__main__':
    c = Client()
    c.do_something()

上述的Boss实例不需要显式传递,受到了保护;Proxy对象相当于一个接口的作用。

LocalProxy代理对象

LocalProxy就是flask框架的werkzeug工具实现的一个代理对象,它接收一个可调用的无参数函数作为参数,内部实现了object对象所有的魔法方法的重写,理论上可以代理任何的对象,不管这个对象的结构是怎么样的。

class LocalProxy(object):
    def __init__(self, local, name=None):
        object.__setattr__(self, '_LocalProxy__local', local)
        object.__setattr__(self, '__name__', name)

    def _get_current_object(self):
        if not hasattr(self.__local, '__release_local__'):
            return self.__local() # 代理对象local必须是可调用的
        try:
            return getattr(self.__local, self.__name__)
        except AttributeError:
            raise RuntimeError('no object bound to %s' % self.__name__)

如果我们想在项目中的任何地方使用我们自己的全局代理对象,我们可以这样做:

# myproxy.py
from werkzeug.local import LocalProxy

class Boss(object):
    def pop(self):
        print('Ok')
        return 'OK'
class OtherObj(object):
    def __init__(self,Obj):
        self.real_obj = Obj()
other = OtherObj(Boss)
def get_boss(Obj=None):
    return Obj.real_obj
    
proxy_boss = LocalProxy(partial(get_boss, other))

get_boss这种形式是动态代理,也就是说在进程运行中由于OtherObj的real_obj属性可能发生变化,proxy_boss代理的对象可能发生改变。

参考

转载于:https://www.cnblogs.com/cwp-bg/p/10084480.html

在C++中实现对象请求代理(如RMI/RPC)一般涉及到以下几个步骤: 1. **定义接口**: 首先,你需要定义一个公共接口(通常是一个纯虚基类),这个接口包含了所有将被远程调用的方法。例如: ```cpp class RemoteInterface { public: virtual void method1() = 0; virtual int method2(string arg) = 0; }; ``` 2. **实现代理类**: 创建一个本地代理类,该类继承自接口,但在实际调用时并不会真正执行远程方法,而是记录并转发给实际的目标对象。比如在CORBA中,你可以使用`ORB`创建代理: ```cpp class LocalProxy : public RemoteInterface { private: RemoteInterface* remoteObject; public: LocalProxy(RemoteInterface* obj) : remoteObject(obj) {} // 转发到远程对象的方法调用 void method1() override { remoteObject->method1(); } int method2(const string& arg) override { return remoteObject->method2(arg); } }; ``` 3. **序列化和反序列化**: 在跨进程或跨机器通信时,你需要将方法调用转换成可以传输的形式(序列化),到达目标后还原(反序列化)。对于C++,可能需要借助第三方库,如CORBA的`CdrStream`或Boost.Serialization。 4. **注册和服务提供**: 为了能在网络上找到服务,需要将代理对象注册到一个命名服务(如CORBA Naming Service)。客户端则通过这个名称查找并获取代理对象。 5. **通信和调用**: 客户端创建一个代理对象,然后通过网络发送请求给服务器。服务器接收到请求后,会从代理对象中提取出真正的方法调用,并执行对应的操作。 6. **错误处理**: 必须考虑网络问题和异常情况,适当地处理可能出现的错误。 注意:以上步骤涉及的库和语法可能会因所使用的RPC框架有所不同,如SOAP、gSOAP、Thrift等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值