python装饰器

桥蕤
• 阅读 232

目录

1.闭包 2.nonlocal 3.装饰器

1.闭包

当一个函数 inner 能够使用 outer函数的变量时,称inner为闭包:

# 演示闭包
def outer():
    i = 4

    def inner():
        sum = i + 1
        print(sum)

    return inner  # 注意这里是函数名(指代函数地址);不是inner(),inner()表示函数调用。


f1 = outer()
print(f1)  # 此时 f1 指代函数地址,还未运行
# print(f1())
f1()  # 调用运行f1函数,等同于 outer()()

运行结果 python装饰器 闭包特点:

  • 函数outer() 内部再嵌套函数inner();
  • 内部函数inner() 使用了外部函数outer() 的变量 i;
  • 外部函数outer() 返回内部函数的函数名inner。

2.nonlocal

nonlocal是关键字,声明了非局部(non-local)也非全局(non-global)的变量,例如闭包函数inner外的函数;变量跟着函数存在而存在,跟着函数销毁而销毁。 它允许我们在inner函数内部 修改outer函数的i变量:

def outer():
    i = 4
    def inner():
        nonlocal i  # 声明变量i的作用域
        sum = i + 1
        i += 1
        print(sum)
    return inner
f1 = outer()
for i in range(5):
    # 使用for循环运行5次
    f1()

运行结果: python装饰器 可以看出5次运行,每次i的值都加了1;直到结束。而把 nonlocal i注释掉会报错,在注释掉i+=1则不会报错: python装饰器

3.装饰器

当一个函数 inner 能够使用 outer函数的变量,当这个变量是一个函数时,这个闭包就是一个装饰器。 在定义一个类时,使用@classmethod和@staticmethod修饰方法,这样的写法就是闭包的语法糖。

# 1.创建一个统计函数运行次数的装饰器
def func_count(func):
    a = 0  # 函数初始值
    def inner(str):# 传入函数及其参数
        nonlocal a  # 在内部函数修改外部函数的变量
        a += 1
        func(str)  # 运行传进来的函数
        print(f'执行了{a}次!')  # 函数每运行一次就提示一次
    return inner

# 2.定义输出函数并使用装饰器
@func_count
def f1(str):
    print(str)

# 3.执行函数
for i in range(5):
    f1('hello world')

运行结果: python装饰器 可以看出装饰器的特点与闭包差不多:

  • 有函数嵌套;
  • 内部函数使用了外部函数的变量,这个变量可以是函数;
  • 外部函数返回内部函数的函数名
  • 为原来的f1函数增加了新的功能:可以查看执行次数。

    多个装饰器

    一个函数可用多个装饰器来装饰,在定义一个装饰器;
    # 创建统计函数执行时间的装饰器
    import time
    def func_time(func):
      time_count = 0
      def inner(str):
          nonlocal time_count  # 在内部函数修改外部函数的变量
          time_start = time.time()  #记录开始时间
          func(str)
          time_count += time.time() - time_start  #新的总运行时间=旧的总运行时间+本次执行时间
          print(f'总执行用时{time_count}')
      return inner
    在原来的基础上改造 f1函数:
    @func_time
    @func_count
    def f1(str):
      a = 0
      for i in range(100000):
          a += 1  # 模拟函数运行时间
      print(f'{str}-{a}')
    同上运行5次 f1函数,运行结果: python装饰器

    带有参数的装饰器

    在为原来函数添加装饰器时,可对装饰器传入参数;具体实现就是三层嵌套的函数:
    # 定义带有参数的装饰器
    def parameter(n):   # 传入装饰器参数
      def outer(func):
          def inner(*args, **kwargs):     # 传入可变参数或不定长参数,*元组类型参数(1,2,3);**字典类型参数(a=1,a=2,a=3)
              for i in range(n):
                  result = func(*args, **kwargs)
              return result   # 如果func没有返回值可以省略不写
          return inner
      return outer
    

@parameter(5) def f1(str): print(f"Hello {str}!")

f1("World")

``` 运行结果: python装饰器

点赞
收藏
评论区
推荐文章
Python进阶者 Python进阶者
2年前
编写一个闭包函数,要实现的功能是计数功能
大家好,我是皮皮。一、前言前几天在Python最强王者交流群有个叫【杰】的粉丝问了一个Python装饰器的问题,这里拿出来给大家分享下,一起学习下。二、解决过程这里【东哥】给出了解答,其实这个题目就是在考你装饰器的内容。代码如下:count0defwrapper(func):definner(args,kwargs):g
Bill78 Bill78
3年前
python装饰器详解
你会Python嘛?我会!那你给我讲下Python装饰器吧!Python装饰器啊?我没用过哎以上是我一个哥们面试时候发生的真实对白。\分割线
Stella981 Stella981
3年前
Python Challenge Level 18
初学Python,挑战一下流行的PythonChallenge,很不幸,卡在了18关~~被字符字节码之间的转换搞得焦头烂额,不过终于搞定了还是很happy的~~~主要的问题就是16进制形式的字符如何转成字节码(注意:不是encoding)如:\'89','50','4e','47','0d','0a','1a','0a','00
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Stella981 Stella981
3年前
Scapy 从入门到放弃
0x00前言最近闲的没事,抽空了解下地表最强的嗅探和收发包的工具:scapy。scapy是一个python模块,使用简单,并且能灵活地构造各种数据包,是进行网络安全审计的好帮手。0x01安装因为2020年python官方便不再支持python2,所以使用python3安装。!(https://oscimg.oschina.net/os
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Stella981 Stella981
3年前
Python 装饰器(Decorator)
Python 装饰器(Decorator)装饰模式有很多经典的使用场景,例如插入日志、性能测试、事务处理等等,有了装饰器,就可以提取大量函数中与本身功能无关的类似代码,从而达到代码重用的目的。下面就一步步看看Python中的装饰器。装饰器本身是一个Python函数,他可以让其他函数在不需要做任何代码变动
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
3A网络 3A网络
2年前
Golang 常见设计模式之装饰模式
Golang常见设计模式之装饰模式想必只要是熟悉Python的同学对装饰模式一定不会陌生,这类Python从语法上原生支持的装饰器,大大提高了装饰模式在Python中的应用。尽管Go语言中装饰模式没有Python中应用的那么广泛,但是它也有其独到的地方。接下来就一起看下装饰模式在Go语言中的应用。简单装饰器我们通过一个简单的例子来