title: Python 装饰器装饰类中的方法

comments: true

date: 2017-04-17 20:44:31

tags: ['Python', 'Decorate']

category: ['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参数,类外面的装饰器就可以直接使用类里面的各种方法,也可以直接使用类的属性。

Python 装饰器装饰类中的方法的更多相关文章

  1. Python 学习 —— 进阶篇(装饰器、类的特殊方法)

    Python基础部分学完之后,在进入其OOP部分前,先理解一下其装饰器这种结构,其功能可类比于Java中的面向切面编程,下面参见具体实例: def log(f): def fn(x): print ' ...

  2. day20-Python运维开发基础(装饰器 / 类中的方法 / 类的方法变属性)

    1. 装饰器 / 类中的方法 / 类的方法变属性 # ### 装饰器 """ 定义:装饰器用于拓展原来函数功能的一种语法,返回新函数替换旧函数 优点:在不更改原函数代码的 ...

  3. 详解Python闭包,装饰器及类装饰器

    在项目开发中,总会遇到在原代码的基础上添加额外的功能模块,原有的代码也许是很久以前所写,为了添加新功能的代码块,您一般还得重新熟悉源代码,稍微搞清楚一点它的逻辑,这无疑是一件特别头疼的事情.今天我们介 ...

  4. Python 使用装饰器装饰类

    1.装饰器装饰函数 了解过或学过装饰器的同学都知道,Python 中的装饰器是可以装饰函数的,如: # 定义一个装饰器 def decorator(func): def inner(*args,**k ...

  5. python 装饰器 对类和函数的装饰

    #装饰器:对类或者函数进行功能的扩展  很多需要缩进的没有进行缩进'''#第一步:基本函数def laxi(): print('拉屎')#调用函数laxi()laxi() print('======= ...

  6. python 进阶篇 函数装饰器和类装饰器

    函数装饰器 简单装饰器 def my_decorator(func): def wrapper(): print('wrapper of decorator') func() return wrapp ...

  7. python 装饰器(七):装饰器实例(四)类装饰器装饰类以及类方法

    类装饰器装饰类方法 不带参数 from functools import wraps import types class CatchException: def __init__(self,orig ...

  8. python 装饰器(八):装饰器实例(五)函数装饰器装饰类以及类方法

    函数装饰器装饰类 单例模式 from functools import wraps def singleton(cls): instances = {} @wraps(cls) def get_ins ...

  9. Python中的多个装饰器装饰一个函数

    def wrapper1(func1): def inner1(): print('w1 ,before') func1() print('w1 after') return inner1 def w ...

随机推荐

  1. oracle目录操作

    1.创建目录 create directory dir_name as 'dir_path'  (dir_path必须事先手动创建) 2.授权 grant read,write on director ...

  2. JavaWeb之Filter过滤器

    原本计划这一篇来总结JSP,由于JSP的内容比较多,又想着晚上跑跑步减减肥,所以今天先介绍Filter以及它的使用举例,这样的话还有些时间可以锻炼锻炼.言归正传,过滤器从字面理解她的话有拦网.过滤的功 ...

  3. python + selenium <四>

    层级定位 swich_to_alert swich_to_frame swich_to_window 1. driver.switch_to_alert().accept()#最简单,直接点击确定关闭 ...

  4. wxpython分割窗研究(解决sashPosition=0无效的BUG)

    用wxpython开发一个简单的exe其实很简单的,但是在开发的过程中会遇到若干的坑.疑问.甚至bug,让人摸不清头脑!恰恰关于这方面的文档是少之又少,看来看去大家还是在官方的文档上加以引用说明,但是 ...

  5. jQuery中$.extend(true,object1, object2);深拷贝对象

    语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 深浅拷贝对应的参数就是[deep],是可选的,为true或false.默认情况是fa ...

  6. "the hypervisor is not running" 故障

    在我们日常服务器管理中,常常会遇到创建虚拟机,如果在一台新部署的 Hyper-V 上新建一个 Virtual Machine 时,出现错误信息:"The virtual machine co ...

  7. SpringMVC4+MyBatis+SQL Server2014+druid 监控SQL运行情况

    前言 在基于SpringMVC+MyBatis的开发过程中,我们希望能看到自己手写SQL的执行情况,在开发阶段我们可以配置log4j在控制台里基于debug模式查看,那么上线后,在生产声我们想查看SQ ...

  8. IOS推送--之开发模式测试

    参考文章:http://blog.csdn.net/showhilllee/article/details/8631734#comments 第一步.下载你工程的开发证书 第二步.从钥匙串访问中导出秘 ...

  9. WPF: 本地化(Localization) 实现

    本文将讨论一种较为方便的本地化方法. 由于在项目中要实现本地化,所以在网上查找相关的解决方案.通过一系列调研,发现实现本地化的方法主要有以下三种: 通过编译项目以设置 x:Uid 并使用 LocBam ...

  10. 基于模糊聚类和最小割的层次化网格分割算法(Hierarchical Mesh Decomposition)

    网格分割算法是三维几何处理算法中的重要算法,具有许多实际应用.[Katz et al. 2003]提出了一种新型的层次化网格分割算法,该算法能够将几何模型沿着凹形区域分割成不同的几何部分,并且可以避免 ...