Pyhton类方法添加装饰器案例解析

在这里插入图片描述

from functools import wraps

def keep_alive(func):
    """装饰器:为方法自动维护长连接"""
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        if not self.conn:
            self.conn = ConnectHandler(**self.device_params)
            self.conn.enable()
        return func(self, *args, **kwargs)
    return wrapper

class RouterClient:
    def __init__(self, device_params):
        self.device_params = device_params
        self.conn = None
    
    @keep_alive
    def execute(self, command):
        return self.conn.send_command(command)
    
    def close(self):
        if self.conn:
            self.conn.disconnect()

# 使用
client = RouterClient(device)
client.execute("show run")  # 自动创建连接
client.execute("show interfaces")  # 复用连接
client.close()  # 显式关闭

1. 如何给类中的方法添加装饰器?

在Python中,给类的方法添加装饰器的方式与普通函数完全一致,直接在方法定义前使用 @装饰器名 即可。例如,在代码中:

class RouterClient:
    @keep_alive
    def execute(self, command):
        return self.conn.send_command(command)

这里的 @keep_alive 会作用于 execute 方法。关键在于装饰器的实现需要正确处理实例方法。因为实例方法的第一个参数是 self,所以装饰器内部的包装函数 wrapper 必须接收 self 作为第一个参数:

def wrapper(self, *args, **kwargs):  # 这里显式接收 self
    if not self.conn:
        self.conn = ConnectHandler(**self.device_params)
        self.conn.enable()
    return func(self, *args, **kwargs)  # 传递 self 给原始方法

client.execute("show run") 被调用时,self 实际上是 RouterClient 的实例,因此装饰器可以正确访问 self.conn


2. @wraps(func) 的目的是什么?

@wraps(func)functools 模块提供的一个装饰器,它的作用是保留被装饰函数(func)的元数据(如 __name____doc__ 等)。如果不使用 @wraps,被装饰后的函数会丢失原始函数的信息:

  • 没有 @wraps 的情况
    print(client.execute.__name__)  # 输出 "wrapper"
    
  • 使用 @wraps 的情况
    print(client.execute.__name__)  # 输出 "execute"
    

这对于调试、生成文档或依赖函数元数据的代码(如某些 Web 框架的路由装饰器)非常重要。@wraps(func) 确保装饰后的函数看起来更像原始函数。


3. keep_alive 中的 if not self.conn 语句,self.conn 是从哪里来的?

self.connRouterClient 类的实例属性。在 RouterClient__init__ 方法中,它被初始化为 None

class RouterClient:
    def __init__(self, device_params):
        self.device_params = device_params
        self.conn = None  # 初始化 conn 为 None

在装饰器的 wrapper 函数中,self 指向调用 execute 方法的 RouterClient 实例。例如:

client = RouterClient(device)
client.execute("show run")  # 此时 self 是 client 实例

当第一次调用 execute 时,self.connNone,装饰器会创建连接并赋值给 self.conn;后续调用时,self.conn 已存在,直接复用。


总结代码逻辑:

  1. 创建实例

    client = RouterClient(device)
    
    • client.conn 初始化为 None
  2. 首次调用 execute

    client.execute("show run")
    
    • 装饰器检查 self.connNone,创建连接并赋值给 self.conn
    • 执行 send_command("show run")
  3. 再次调用 execute

    client.execute("show interfaces")
    
    • self.conn 已存在,直接复用连接。
    • 执行 send_command("show interfaces")
  4. 显式关闭连接

    client.close()
    
    • 调用 conn.disconnect() 关闭连接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值