使用装饰器装饰类方法,并在装饰器中调用类方法

类外的装饰器方法装饰类方法,并调用该类的其他方法

场景:链接数据库的类,在执行数据库方面的操作时,经常会断开,此时需要调用该类的连接数据库方法来重新链接到数据库

class My_dbclient():
    def __init__(self):
        self.try_count=10
        self.connect()

    def connect(self):
        print("数据库链接成功")


    def insert(self):
        # 可能会出现数据库断开链接的异常
        print("正在执行保存操作")
        for i in range(self.try_count):
            try:
                print("保存数据")
                # raise NameError
                return
            except Exception:
                time.sleep(1)
                self.connect()
                print(traceback.format_exc())

    def select(self):
        # 可能会出现数据库断开链接的异常
        print("查询数据")

    def delete(self):
        # 可能会出现数据库断开链接的异常
        print("删除数据")

就像insert方法中这样,可以捕获异常,并重新链接,然后再操作。

但是,无论增删改查,都需要这样来写,代码冗余。很自然,使用装饰器来解决。

示例:

常规的装饰器写法

def catch_error(fun):
    def wrapper(*args, **kwargs):
        for i in range(1, 10):
            try:
                fun(*args, **kwargs)
                return
            except Exception:
                time.sleep(1)
                print("链接错误---{}---次".format(i))
                print("调用数据库链接方法,重新链接数据库")
        print("信息保存失败")

    return wrapper


@catch_error
def insert():
    print("开始执行插入语句")
    raise TimeoutError

现在我们想要装饰类方法,并在捕获数据库链接异常后,调用数据库链接方法重新链接。

解决办法:

  • 在装饰器的内部函数 wrapper 的参数中,增加self参数
  • 并在调用的函数fun中,增加self参数

如下,就可以使用self来调用connect这个方法了,同时,

def catch_error(fun):
    def wrapper(self,*args, **kwargs):
        for i in range(1, 10):
            try:
                fun(self,*args, **kwargs)
                return
            except Exception:
                time.sleep(1)
                print("链接错误---{}---次".format(i))
                print("调用数据库链接方法,重新链接数据库")

                self.connect()

        print("信息保存失败")

    return wrapper

完整代码:

import time
import traceback


def catch_error(fun):
    def wrapper(self,*args, **kwargs):
        for i in range(1, 10):
            try:
                fun(*args, **kwargs)
                return
            except Exception:
                time.sleep(1)
                print("链接错误---{}---次".format(i))
                print("调用数据库链接方法,重新链接数据库")

                self.connect()

        print("信息保存失败")

    return wrapper


@catch_error
def insert():
    print("开始执行插入语句")
    raise TimeoutError


class My_dbclient():
    def __init__(self):
        self.try_count = 10
        self.connect()

    def connect(self):
        print("数据库链接成功")

    @catch_error
    def insert(self):
        # 可能会出现数据库断开链接的异常
        print("保存数据")
        raise TimeoutError

    def select(self):
        # 可能会出现数据库断开链接的异常
        print("查询数据")

    def delete(self):
        # 可能会出现数据库断开链接的异常
        print("删除数据")


if __name__ == '__main__':
    t = My_dbclient()
    t.insert()

你可能感兴趣的:(python,装饰器,Pythonic)