首页 热点资讯 义务教育 高等教育 出国留学 考研考公

PYTHON里的装饰器能装饰类吗

发布网友 发布时间:2022-04-21 17:58

我来回答

2个回答

热心网友 时间:2022-04-18 03:54

可以的啦

# -*- coding: UTF-8 -*-
from functools import wraps

__author__ = 'lpe234'


def singleton(cls):
    """
    装饰器 实现单例模式
    :param cls:
    :return:
    """
    instances = {}

    @wraps(cls)
    def _singleton(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return _singleton


@singleton
class SelfClass(object):
    pass


def main():
    s1 = SelfClass()
    s2 = SelfClass()
    assert s1 is s2

if __name__ == '__main__':
    main()

热心网友 时间:2022-04-18 05:12

Python 装饰器装饰类中的方法

目前在中文网上能搜索到的绝大部分关于装饰器的教程,都在讲如何装饰一个普通的函数。本文介绍如何使用Python的装饰器装饰一个类的方法,同时在装饰器函数中调用类里面的其他方法。本文以捕获一个方法的异常为例来进行说明。

有一个类Test, 它的结构如下:

class Test(object):
def __init__(self):
pass

def revive(self):
print('revive from exception.')
# do something to restore

def read_value(self):
print('here I will do something.')
# do something.

在类中有一个方法read_value(),这个方法在多个地方被调用。由于某些原因,方法read_value有可能随机抛出Exception导致程序崩溃。所以需要对整个方法做try ... except处理。最丑陋的做法如下面的代码所示:

class Test(object):
def __init__(self):
pass

def revive(self):
print('revive from exception.')
# do something to restore

def read_value(self):
try:
print('here I will do something.')
# do something.
except Exception as e:
print(f'exception {e} raised, parse exception.')
# do other thing.
self.revive()

这样写虽然可以解决问题,但是代码不Pythonic。

使用装饰器来解决这个问题,装饰器函数应该写在类里面还是类外面呢?答案是,写在类外面。那么既然写在类外面,如何调用这个类的其他方法呢?

首先写出一个最常见的处理异常的装饰器:

def catch_exception(origin_func):
def wrapper(*args, **kwargs):
try:
u = origin_func(*args, **kwargs)
return u
except Exception:
return 'an Exception raised.'
return wrapper


class Test(object):
def __init__(self):
pass

def revive(self):
print('revive from exception.')
# do something to restore

@catch_exception
def read_value(self):
print('here I will do something.')
# do something.

这种写法,确实可以捕获到origin_func()的异常,但是如果在发生异常的时候,需要调用类里面的另一个方法来处理异常,这又应该怎么办?答案是给wrapper增加一个参数:self.

代码变为如下形式:

def catch_exception(origin_func):
def wrapper(self, *args, **kwargs):
try:
u = origin_func(self, *args, **kwargs)
return u
except Exception:
self.revive() #不用顾虑,直接调用原来的类的方法
return 'an Exception raised.'
return wrapper


class Test(object):
def __init__(self):
pass

def revive(self):
print('revive from exception.')
# do something to restore

@catch_exception
def read_value(self):
print('here I will do something.')
# do something.

只需要修改装饰器定义的部分,使用装饰器的地方完全不需要做修改。

下图为正常运行时的运行结果:

下图为发生异常以后捕获并处理异常:

通过添加一个self参数,类外面的装饰器就可以直接使用类里面的各种方法,也可以直接使用类的属性。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com