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

什么是返回函数?

我们知道,一个函数中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. PSP总结报告1

    回答作业问题 1.回想一下你曾经对计算机专业的畅想 我高考后报考的是计算机科学与技术,当时对计算机技术基本了解为零,当时以为什么东西都会用到计算机,学计算机以后不会找不到工作,刚开学的时候对计算机一窍 ...

  2. TeamWork#2,Week 5,Our Measurement of Contribution to the Team

    经过了今天下午将近两个小时的激烈讨论,我们最终确定了我们的团队贡献分的分配方式,这种方式是我们团队都能接受的. 我们的分配方式一定程度上借鉴了valve公司的队友评估原则,但是又不单单是这样.我们的分 ...

  3. C#中周,月,第几周,周开始结束时间de方法总结

    1.c#获取当前时间是本年的第几周,本月的第几周 private static int getWeekNumInMonth(DateTime daytime) { int dayInMonth = d ...

  4. 每天学一点easyui②

    Form插件 <!DOCTYPE html> <html>       <head>         <meta charset="utf-8&qu ...

  5. 配置树莓派/Linux默认声卡设备

    1.设置默认声卡为USB声卡 在$HOME下新建.asoundrc $cd $HOME $nano .asoundrc 输入以下内容 defaults.ctl.card 1 defaults.pcm. ...

  6. android--实现通过点击链接打开apk(应用图标在桌面消失)

    首先在AndroidManifest.xml的MAIN Activity下追加以下内容.(启动Activity时给予) ※必须添加项 <intent-filter> <action ...

  7. angularJS1笔记-(19)-angular异步加载包的方式

    我们平时写的导入包的方式都是同步方式,有时候会显得过于卡顿,这样我们就可以使用异步加载的方式. script.js方式: 执行结果为: 异步加载还可以加载多个即为script([,,,],functi ...

  8. 解决登录不上网页得tomcat(授权manager-gui角色的操作如下)

    1:编辑/usr/local/tomcat/conf/tomcat-users.xml文件,在没有注释的内容中添加: <role rolename="manager-gui" ...

  9. Beta阶段——第四篇 Scrum 冲刺博客

    i. 提供当天站立式会议照片一张: ii. 每个人的工作 (有work item 的ID) (1) 昨天已完成的工作: 充值与账单的数据库操作结合,实现余额功能 (2) 今天计划完成的工作: 用户权限 ...

  10. 看懂Qt源代码-Qt源码的对象数据存储

    第一次看Qt源代码的人都会被其代码所迷惑,经常会看到代码中的d_ptr成员.d_func(函数)和Q_DECLARE_PRIVATE等奇怪的宏,总是让人一头雾水,下面这篇文章转自http://www. ...