开放封闭原则:

开放对扩展

封闭修改源代码

改变了人家调用方式

装饰器结构

"""

默认结构为三层!!!每层返回下一层内存地址就可以进行执行函数,

传参:语法糖中的传参可以在地二层中进行判断传入。

第一层:传送语法糖中的参数

第二层:传送外部函数的名称

第三层:传送外部函数的参数

被装饰器装饰的函数名即使没有被调用(因为有@xxx,会触发运行装饰器),

(装饰器工厂函数)定义装饰器的代码已经运行了(最内部的那个函数并没有运行),

(把被装饰的原函数引用赋值给了装饰器内部的那个函数名),当下边通过该函数名调用时,

会调用到装饰器内部的那个函数()

装饰器:在不修改函数源代码的基础上,添加函数功能

"""

def Wrapper(*args,**kwargs): #获取`@Wrapper(args)`传入参数

def Outter(func_name): #获取装饰器所装饰函数的名称

def Inner(*args,**Kwargs): #获取`def func(*args,**kwargs):`的传入参数

ret = func_name(*args,**kwargs) #执行装饰器所装饰的函数

return ret #将返回值传给被装饰的函数

return Inner #返回`Inner`的内存地址,方便调用

return Outter #返回`Outter`的内存地址,方便调用

@Wrapper(args) #`func = Outter(func) = Wrapper(args)`装饰器进行传参

def func(*args,**kwargs): #定义被装饰函数

return func.__name__ #定义函数返回值

返回装饰器的被装饰函数名

from functools import wraps

def warpper(f):

@wraps(f) #显示被装饰的函数

def inner(*args,**kwargs):

# print(f.__name__)

print(f)

return inner #

def aa():

print(1)

aa = warpper(aa)

print(aa.__name__) # 显示被装饰的函数名

账户认证(简易版)

def Wrapper(auth_type): #默认使用Wrapper名称,获取语法糖的参数

def Outer(func_name): #获取传入参数的名称

def file(*args,**kwargs): #获取传入参数的参数

print('这是在file函数中')

ret = func_name(*args,**kwargs)

print('file函数装饰完毕')

return ret

def net(*args,**kwargs):

print('这个是在网络函数中')

ret = func_name(*args,**kwargs)

print('网络函数执行结束')

return ret

if auth_type == 'localfile': #对传入参数进行判断返回不同结果

return file

elif auth_type == 'net':

return net

else:

print('该函数没有被装饰')

return Outer

@Wrapper(auth_type='net') #语法糖进行传参

def Login(username):

print(f'Welcome {username} Login.')

Login('longlong') #大神登陆啦!

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

使用类来写装饰器

前两天发现了装饰器可以直接使用类来写,分享一下,需要用类里面的__call__方法,__call__方法就是可以把这个实例当成一个函数来调用,如果正常使用类里面的方法的话,实例方法要先实例化类,然后才能调用,静态方法、类方法则需要用类名或者实例化之后的对象来调用,而实例化之后的这个对象,是不能被调用的,__call__方法就是把这个实例变成一个可以调用的对象,也就是说实例化之后,这个对象就可以和一个普通函数一样被调用。

示例代码如下:

class Foo:

def __call__(self, *args, **kwargs):

print('call....')

def test(self):#

print('test....')

if __name__ == '__main__':

t = Foo()#实例化类

t.test()#正常调用实例方法

t()#直接调用实例化之后的对象

理解了上面的之后,就可以使用class来写一个装饰器了,计算程序的运行时间,当然思想和以前用函数写装饰器是一样的

class Fuck(object):

def __init__(self, func):

self.func = func

def __call__(self, *args, **kwargs):

import time

start_time = time.time()

res = self.func(*args, **kwargs)

end_time = time.time()

print('the function "%s" run time is %s' % (self.func.__name__,

(end_time - start_time)))

return res

@Fuck

def run(name):

import time

time.sleep(1)

return 'sb_%s' % name

print(run('hyf'))

python类装饰器详解-Python 装饰器详解相关推荐

  1. python类高级用法_十.python面向对象高级用法

    1.反射 1.1 什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的 ...

  2. Python类的构造方法__init__(self)和析构函数__del__详解

    一.构造方法__init__(self) __init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法.一般用来对实例的属性进行初使化,如果不提供,P ...

  3. python教程实例-python 类和实例 - 刘江的python教程

    类和实例 阅读: 19079 评论:6 类,英文名字Class,有"类别","分类","聚类"的意思.必须牢记类是抽象的模板,用来描述具有相 ...

  4. python 类继承list,为什么继承 Python 内置类型会出问题?!

    本文出自"Python为什么"系列,请查看全部文章 不久前,Python猫 给大家推荐了一本书<流畅的Python>(点击可跳转阅读),那篇文章有比较多的"溢 ...

  5. python类的参数_在Python中使用类中的参数

    当我在Codecademy上学习 Python时,我遇到了这个问题,代码如下: class Employee(object): def __init__(self, name): self.name ...

  6. python类继承实例_Python实现类继承实例

    Python是一种解释型.面向对象.动态数据类型的高级程序设计语言,本文就举一例Python类继承的实例. 实例代码如下: #! /usr/bin/python # Filename: inherit ...

  7. python类中成员的的调用

    python类中成员的调用 python类中的方法到底到底是方法还是函数取绝于调用者, 当类名调用这个方法时他是一个函数 class Foo(object):def f1(self):print(&q ...

  8. 【Python基础】07、Python类与面向对象

    一.面向对象编程(OOP) 程序=算法+数据结构=指令+数据 1.代码可以选择以指令为核心或以数据为核心进行编写 两种范型: 以指令为核心:围绕"正在发生什么"进行编写 面向过程编 ...

  9. Python类继承对象

    类声明从object继承有什么理由吗? 我刚刚找到了执行此操作的代码,但找不到很好的理由. class MyClass(object):# class code follows... #1楼 难学Py ...

  10. python类和对象_Python类和对象

    python类和对象 Python is an object-oriented programming language. Python Classes and Objects are the cor ...

最新文章

  1. 开源网站Open-Open
  2. error LNK2001:错误解决过程
  3. CodeForces - 1196F K-th Path(最短路+思维)好题
  4. leetcode169. 多数元素——pygo
  5. 运动后肌肉酸痛怎么办?
  6. 函数 单片机glint_PIC单片机CCS之C语言(#BIT的用法)
  7. 西门子修复因使用第三方组件引起的90多个漏洞
  8. 浮动的三个特点很重要。
  9. java linux ping ip,java linux ping命令
  10. automake连载--Linux下使用autoconfig automake进阶
  11. Java重写《C经典100题》 --08
  12. APP性能测试之GT 测试
  13. 软件压力测试报告要怎么写,如何做接口压力测试?压力测试报告应该包含哪些结果?...
  14. 矩阵的乘法(python、matlab、excel的不同实现方法)
  15. WinISO5.3 注册码 不需要注册机
  16. 基于java的密码字典生成
  17. 怎么用python写脚本刷金币_教你如何利用Python实现王者荣耀自动刷金币脚本
  18. DSP 2812 的经典资料
  19. Paper reading (二十二):Integrated omics: tools, advances and future approaches
  20. 史密斯探测证实,BioFlash可检出空气中的SARS-CoV-2变异株,包括德尔塔和德尔塔+

热门文章

  1. 如何定义一个自己的可复用的JS文件
  2. Oracle根据日期计算某月的天数
  3. MS 的SPACE很不好的说
  4. 如果不能调试存储过程
  5. SpringMVC 运行过程
  6. 【Linux】【Services】【Package】rpm
  7. magic_quotes_gpc和magic_quotes_runtime的区别和用法详解
  8. Substring with Concatenation of All Words
  9. android fragment+ FragmentTabHost+viewpager 切换状态不保存的问题
  10. 转载-隐藏在手机中的第二个操作系统