因为装饰器需要用到返回函数的知识,所以在这里将返回函数和装饰器合并讲解。

什么是返回函数?

我们知道,一个函数中return可以返回一个或者多个值,但其实,return不仅可以返回值,还可以返回函数。

实例:

def col(*arg):
def sum():
res_sum=0
for i in arg:
res_sum=res_sum+i
return res_sum
return sum()
a=col(1,2,3,4,5)
print(a)
#结果:15
#a=col(1,2,3,4,5) ==〉
#即a=sum,并且arg=(1,2,3,4,5)也被传入sum中了
#a()==sum()

并且因为sum()定义在col()函数中,所以sum()继承了col()函数的局部变量和参数,这就是闭包。(比如,col()的arg参数就被sum()所继承)

下面来看一个我在检验上面加红的句话时所碰到的一个问题:

#还是用上面这段代码。稍稍修改一下
def col(*arg):
res_sum=0 #注意:将这句话移动到这里了
def sum():
for i in arg:
res_sum=res_sum+i
return res_sum
return sum()
a=col(1,2,3,4,5)
print(a()) 结果报错:local variable 'res_sum' referenced before assignment
#既然内部函数可以引用外部函数的变量,为什么res_sum没有被内#部函数所引用?

为啥会报错?我当时很是疑惑,后来终于弄明白,错在这句:res_sum=res_sum+i

这句导致内部函数修改了外部函数的局部变量res_sum,这时,Python认为res_sum是内部函数的局部变量,而res_sum=res_sum+i之前并没有事先定义res_sum,所以当然会发生这种错误。

所以,需要这样进行修改:

def col(*arg):
res_sum=0
def sum():
for i in arg:
a=res_sum+i #在内部函数中定义一个新的变量a
return a
return sum
a=col(1,2,3,4,5)
print(a())

什么是装饰器?

def login():
pass
@login #关键字@
def open():
pass

上例就是一个装饰器的例子。

装饰器的作用:

当我们定义了open函数后(可以帮助我们打开某个文件),过了一段时间,发现我们需要在进行open之前进行验证用户,如何在不修改open函数的条件下将login函数和open函数进行结合,即:运行open之前先运行login? 这里就要用到装饰器。

下面我们来看一个真正的装饰器的实例:

def login(fun):
def real_login():
print('please input your password')
return fun()
return real_login
@login
def open():
print('hello world')
open()

@login相当于open=login(open)   也就是将open函数偷梁换柱了一番。

当我们运行open()时:

open=login(open)
  #login(open)中的参数及局部变量:fun=open(原)
  #open=login(open)的返回值!
  #即:open=real_login
  
open()=real_login()
  #因为real_login定义在login之中,所以继承其参数和局部变量
  #所以整体来看open()==login(open)+real_login()+open()

实现一个可以接受任意参数的装饰器:

def outer(func):
def inner(*args,**kwargs):
print('start')
r=func(*args,**kwargs) # 这里func(*args,**kwargs)相当于f(a,b)
print('end')
return r
return inner @outer
def f(a,b):
print(a+b)
@outer
def f2(a,b,c):
print(a+b+c) f(1,2)
f2(1,2,3)
#结果:
start
3
end
start
6
end

python基础之函数进阶之函数作为返回值/装饰器的更多相关文章

  1. 【python基础】第19回 多层,有参装饰器 递归 二分法

    本章内容概要 1. 多层装饰器 2. 有参装饰器 3. 递归函数 4. 算法(二分法) 本章内容详解 1. 多层装饰器 1.1 什么是多层装饰器 多层装饰器是从下往上依次执行,需要注意的是,被装饰的函 ...

  2. python函数进阶(函数参数、返回值、递归函数)

    函数进阶 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形 ...

  3. Python基础之文件处理、函数、内置函数 (三)

    内置函数 一 详细见python文档,请点击 文件操作 操作文件时,一般需要经历如下步骤: 打开文件 操作文件 一.打开文件 文件句柄 = file('文件路径', '模式') 注:python中打开 ...

  4. python基础十四之匿名函数

    匿名函数 处理简单问题的简化函数,关键字lambda. # 格式:函数名 = lambda 参数:返回值 anonymity = lambda s: s ** 0.5 print(anonymity( ...

  5. 十三. Python基础(13)--生成器进阶

    十三. Python基础(13)--生成器进阶 1 ● send()方法 generator.send(value) Resumes the execution, and "sends&qu ...

  6. python基础篇之进阶

    python基础篇之进阶 参考博客:http://www.cnblogs.com/wupeiqi/articles/5115190.html python种类 1. cpython  使用c解释器生产 ...

  7. python 全栈开发,Day12(函数的有用信息,带参数的装饰器,多个装饰器装饰一个函数)

    函数的执行时,*打散.函数的定义时,*聚合. from functools import wraps def wrapper(f): # f = func1 @wraps(f) def inner(* ...

  8. 12、Python函数高级(命名空间、作用域、装饰器)

    一.名称空间和作用域 1.命名空间(Namespace) 命名空间是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的. 命名空间提供了在项目中避免名字冲突的一种方法.各个命名空 ...

  9. python 函数结果缓存一段时间的装饰器

    把函数结果缓存一段时间,比如读取一个mongodb,mongodb中的内容又在发生变化,如果从部署后,自始至终只去读一次那就感触不到变化了,如果每次调用一个函数就去读取那太频繁了耽误响应时间也加大了c ...

随机推荐

  1. 阿里云oracle启动失败

    1.监听启动失败: 将$ORACLE_HOME/network/admin 中的listener.ora中的主机名改为localhost 2.sqlplus中startup启动失败 ,出现ORA-00 ...

  2. iOS自学-混合编程

    OC调用swift,引入头文件 #improt "工程名字-swift.h" swift调用OC,在桥梁文件里面引入OC文件 的头文件 尽情混合编程吧...

  3. JavaScript实现弹出层(以layer.open为例)

    首先,引用layer,自行下载. 添加如下两行 <script src=" ../layer/jquery.min.js"></script> <sc ...

  4. html border画三角形

    最近遇到了问题就是画推进条类似于

  5. 浅谈Java中的Hashmap

    HashMap:   java.lang.Object ∟ java.util.AbstractMap<K,V> ∟ java.util.HashMap<K,V> 类型参数: ...

  6. 数据库:XML,解析Dom4J

    package com.itheima.util; import java.io.FileOutputStream; import java.net.URL; import org.dom4j.Doc ...

  7. ASP.NET MVC 2.0 参考源码索引

    http://www.projky.com/asp.netmvc/2.0/System/Web/Mvc/AcceptVerbsAttribute.cs.htmlhttp://www.projky.co ...

  8. Spring框架的补充

    1.使用xml文件方式配置bean ——property标签ref属性和ref标签区别 <property name=“bean” ref="myBbean" /> r ...

  9. java类和对象

    类是对象的抽象 对象是类的一个实例类 对象 = new 类();拿对象可以操作这个类里的方法 java类与对象的区别是个老生常谈的问题,刚开始学java的时候就开始接触类和对象,今天来总结一下他们之间 ...

  10. Java开发中的23种设计模式详解(转载)

    前学习过一段时间的设计模式,总是感觉学习的不够清楚.现在再重新复习一下,原文地址:https://blog.csdn.net/doymm2008/article/details/13288067 一. ...