step1.

先看个代码吧:

def f():
print('') f=lambda a:a +100  #覆盖上面的函数f print(f)  #函数名指函数所在内存中的位置,入带后面括号表示执行函数
print(f(10)) out:
<function <lambda> at 0x101b7b6a8>
110

以上code说明:

1.在def 函数时,以顺序执行,如果相同的函数名,会被最后函数覆盖以前的

2.如果直接func名而没有后面的圆括号的话,只指向函数在内存中的位置

3.lambda表达式会自动return结果,而def需要定义return值


step2:

python中可想函数传递参数,并将参数转变为本地变量存在于函数内部。

def f(x):
print(locals()) f('a') out: {'x': 'a'}

step3:

python函数中可以嵌套函数,这就说明了我们可以在函数里定义函数,而且现有的作用域和函数的变量生存周期依旧适用。

def outer():
x='hello world'
def inner():
print(x) #
inner() # outer() out:
hello world

#1 中发生了什么,函数inner需要一个x的变量,去查找x的变量,但本地变量中没有,查找失败后去上一层的作用域中去寻找,而x变量在上一层函数的作用域中。

对outer来说,x是本地变量,但函数inner可以访问封闭的作用域

#2 中,调用了inner函数,python解释器会优先查找本地的变量x


step4:

def outer():
x='hello world'
def inner():
print(x)
return inner  #1 foo=outer()  #2
print(foo)
foo() out:
<function outer.<locals>.inner at 0x10137b6a8>
hello world

#1与step3区别,我们将函数inner的内存地址给返回了

#2,将函数outer的返回值赋值于变量foo,也就是说,foo() 执行时,实际上执行了inner()。

但inner函数集成了outer函数中的本地变量,outer外面,没有x这个变量,为什么能执行呢??

这是因为python中有一个叫”函数闭包”的特性,怎么理解呢?嵌套定义在非全局作用域中的函数,能够记住它在被定义时候它所处的封闭命名空间。

函数outer每次在被调用的时候,函数inner都会被重新定义,现在变量x的值不会变化,所以每次执行的逻辑和结果都一样,那么如果x是变化的呢?


step5:

def outer(x):
def inner():  
print(x)  #1
return inner print1=outer(1)
print2=outer(2) print1()
print2() out:
1
2

从这个我们能够看到“闭包”:被函数记住的封闭作用域,能够被用来创建自定义的函数。

事实上,我们并不是传递参数1或2给inner函数,我们实际上是定义了能够打印各种数字的自定义版本。


step6:装饰器

终于说到装饰器上了。。。。。

装饰器其实就是一个闭包而已,把func作为参数,然后返回一个替代版的函数,其实真正执行的是inner内部的流程

def outer(func):
def inner():
print('before some_func')
res = func()
print(res+1)
print(('after some_func'))
return res+1
return inner
def foo():
return 1
f1=outer(foo) #1
f1() out:
before some_func
2
after some_func

在这我们可以认为变量f1是函数foo的的装饰器。但这么写有点太low了是不是,所以python中有个优雅的@符号,太装逼了。。。可以这么写:

def outer(func):
def inner():
print('before some_func')
res = func()
print(res+1)
print(('after some_func'))
return res+1
return inner
@outer
def foo():
return 1
foo() out: before some_func
2
after some_func

看到没,执行结果一毛一样有木有。


step7:
装饰器用法:
@+函数名
功能:1.自动执行函数(outer函数),并且将下面的函数名f1当做参数
          2.将outer函数的返回值,重新赋值给f1 
需要注意的两点:
1.有return值得才是完整的装饰器。
2.闭包中返回的inner必须是函数的名称func,并非是func(),如果带了括号,那就是执行函数了, inner中返回为None,因为inner中没有return或者return值为其他了。

step8:
有同志就问了,这特么是一个没有参数的,那如果我自己定义的函数有一个参数咋弄。
那我们就用函数中的万能参数*args **kwargs来造一个通用的装饰器吧:
def outer(func):
def inner(*args,**kwargs):
print('before some_func')
res = func(*args,**kwargs)
print(('after some_func'))
return res
return inner
@outer
def foo():
print(111)
foo() @outer
def foo1(li,d):
print('args:%s'%li)
print('kwargs:%s'%d)
foo1('fuck','U')
===============
out:
before some_func
111
after some_func
before some_func
args:fuck
kwargs:U
after some_func

step9:

多层装饰器

装饰器类似于俄罗斯套娃,可以一层套一层,譬如:

def outer(func):
def inner(*args,**kwargs):
print('before some_func')
res = func(*args,**kwargs)
print(('after some_func'))
return res
return inner @outer1
@outer
def foo1(li,d):
print('args:%s'%li)
print('kwargs:%s'%d)
foo1('fuck','U') ====================
out:
before:this is outer1
before some_func
args:fuck
kwargs:U
after some_func
after:this is outer1 again!

未完待续。。。

 

python基础之:九步认识装饰器的更多相关文章

  1. Python菜鸟之路:Python基础-逼格提升利器:装饰器Decorator

    一.装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等. 装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身 ...

  2. python 基础篇 11 函数进阶----装饰器

    11. 前⽅⾼能-装饰器初识本节主要内容:1. 函数名的运⽤, 第⼀类对象2. 闭包3. 装饰器初识 一:函数名的运用: 函数名是一个变量,但他是一个特殊变量,加上括号可以执行函数. ⼆. 闭包什么是 ...

  3. python基础之闭包函数和装饰器

    补充:全局变量声明及局部变量引用 python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量 global关键字用来在函数或其 ...

  4. Python-Day4 Python基础进阶之生成器/迭代器/装饰器/Json & pickle 数据序列化

    一.生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面 ...

  5. Python基础2:反射、装饰器、JSON,接口

    一.反射 最近接触到python的反射机制,遂记录下来已巩固.但是,笔者也是粗略的使用了__import__, getattr()函数而已.目前,笔者的理解是,反射可以使用户通过自定义输入来导入响应的 ...

  6. Python基础(7)闭包函数、装饰器

    一.闭包函数 闭包函数:1.函数内部定义函数,成为内部函数, 2.改内部函数包含对外部作用域,而不是对全局作用域名字的引用 那么该内部函数成为闭包函数 #最简单的无参闭包函数 def func1() ...

  7. python基础编程: 函数示例、装饰器、模块、内置函数

    目录: 函数示例 装饰器 模块 内置函数 一.函数示例: 1.为什么使用函数之模块化程序设计: 不使用模块程序设计的缺点: 1.体系结构不清晰,可主读性差: 2.可扩展性差: 3.程序冗长: 2.定义 ...

  8. Python基础(闭包函数、装饰器、模块和包)

    闭包函数 格式: def 函数名1(): def 函数名2(): 变量 = 值 return 变量 return 函数名2 func = 函数名1() key = func()

  9. python基础补漏-05-生成器和装饰器

    [1]生成器 很难用简单的语言描述生成器. 生成器:从字面上来理解,就是以某种规则为基础,不断的生成数据的工具 生成器函数: 在函数中如果出现了yield关键字,那么该函数就不再是普通函数,而是生成器 ...

随机推荐

  1. 【最短路+较复杂处理】PAT-L3-005. 垃圾箱分布

    L3-005. 垃圾箱分布 大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁都不愿意守着垃圾箱住.所以垃圾箱的位置必须选在到所有居民点的最短距离最长的地方[此处为第一重排序选择的条件],同时还要保 ...

  2. python3 读取avro文件

    官网示例文档:http://avro.apache.org/docs/current/gettingstartedpython.html#download_install 需要注意的是,官网给出的是p ...

  3. 2019牛客多校B Beauty Values——思维题

    题目 求所有子区间中不同元素之和. 分析 枚举相邻的相同数字形成的区间,计算它是哪些区间的子区间,每次有-1的贡献,将其从总贡献中减去. #include<bits/stdc++.h> u ...

  4. MongoDB 副本集的常用操作及原理

    本文是对MongoDB副本集常用操作的一个汇总,同时也穿插着介绍了操作背后的原理及注意点. 结合之前的文章:MongoDB副本集的搭建,大家可以在较短的时间内熟悉MongoDB的搭建和管理. 下面的操 ...

  5. NetworkX系列教程(2)-graph生成器

    小书匠Graph图论 本节主要讲解如何快速使用内置的方法生成graph,官方的文档在这里,里面包含了networkX的所有graph生成器,下面的内容只是我节选的内容,并将graph画出来而已. 声明 ...

  6. 数据结构实验之查找三:树的种类统计(SDUT 3375)

    C: #include <stdio.h> #include <stdlib.h> #include <string.h> struct node { char d ...

  7. 使用dig进行DNS查询

    dig全称Domain Information Groper,是一个DNS域名信息查询的工具,可以使用来查看域名解析的过程. dig是linux下自带的工具,如果要在windows下使用需要自行下载和 ...

  8. Spring-Cloud-Eureka实例

    SpringCloud实现服务注册中心 注册中心这么关键的服务,如果是单点话,遇到故障就是毁灭性的.在一个分布式系统中,服务注册中心是最重要的基础部分,理应随时处于可以提供服务的状态.为了维持其可用性 ...

  9. springboot连接redis进行CRUD

    springboot连接redis进行CRUD: 1.添加以下依赖: <dependency> <groupId>org.springframework.boot</gr ...

  10. springboot集成Kafka

    kafka和MQ的区别: 1)在架构模型方面, RabbitMQ遵循AMQP协议,RabbitMQ的broker由Exchange,Binding,queue组成,其中exchange和binding ...