python基础之函数进阶之函数作为返回值/装饰器

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

什么是返回函数?

我们知道,一个函数中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)<function col.<locals>.sum at 0x029102B8>
#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      这句导致内部函数修改了外部函数的局部变量,而这是不被允许的!!!!

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

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()
时间: 2024-11-10 14:55:43

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

python基础(八):函数

函数就是将一些语句集合在一起的部件,他们能够不止一次的程序中运行,函数还能够计算出一个返回值,并能够改变作为函数输入的参数.而这些参数在代码运行时每次都不同.以函数的形式去编写一个操作可以使它成为一个广泛的应用工具. 基本格式: def 函数名: 函数体 return 返回值 定义和调用 定义函数按照前面的基本格式定义函数,调用函数时要使用函数名加括号来调用函数,括号中可以包含一个或多个参数.这些参数将会传递给函数头部的参数名. #定义 def test(x,y): return x*y #调用

python_day04 函数嵌套 名称空间和作用域 闭包 装饰器 迭代器 生成器 列表解析 三元表达式 生成器表达式

本节课重要知识点内容如下: 函数嵌套 名称空间和作用域 闭包 装饰器 迭代器 生成器 列表解析 三元表达式 生成器表达式 1.函数嵌套 函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数 def bar(): print('from nbar')def foo(): print('from foo') bar()foo()def max2(x,y): if x > y: return x else: return ydef max4(a,

javascript函数的声明,及返回值

<1> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <!--js中声明函数的方法--> <script type="text/javascript"> //因为javascript是弱类型的语言,所以参数不需要加类型.函数的也不需要像c#那样要求所以路径都需要有返回值(这个不像c#语言,而且c#

如何在函数外部获取ajax的返回值?

问题:今天在开发的过程中,遇到一个小问题,就是在将ajax获取数据部分的代码封装在函数内,将ajax获取的值作为函数的返回值. 抱着爱钻研的精神,最终得到了解决方案,在这里整理出来方便以后查阅. 尝试1:同步调用,直接在ajax函数中return值 function getAjax(){ var result = 1; $.ajax({ url : 'test.php', type : "post", data : {}, async : false, success : functi

C#中的函数(二) 有参有返回值的函数

接上一篇 C#中的函数(-) 无参无返回值的函数 http://www.cnblogs.com/fzxiaoyi/p/8502613.html 这次研究下C#中的函数(二) 有参有返回值的函数 依然写一个小例子,用来测试 跟上一个例子差不多,区别就是MyFunction有二个参数a,b,返回二个数相加的值 F5调试运行,中断后转到反汇编 这里很明显看到不同了 这里就得讲到参数传递的方式,参数从左向右依次存入寄存器ecx edx 但是不同的编程语言有不同的传递参数的方式,有空再写一篇文章介绍下 要

[转]C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

本文转自:http://www.cnblogs.com/landeanfen/p/5501487.html 阅读目录 一.void无返回值 二.IHttpActionResult 1.Json(T content) 2.Ok(). Ok(T content) 3.NotFound() 4.其他 5.自定义IHttpActionResult接口的实现 三.HttpResponseMessage 四.自定义类型 五.总结 正文 前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学

Python基础知识(2)——函数

Python函数 全球变量 < 局部变量 传参方法: 位置传参 和 关键字传参(常用关键字传参) 函数里定义参数默认值需放在最后 错误的 Def func_name(arg=100,arg1,arg2,arg,3): 正确的 Def func_name(arg1,arg2,arg,3,arg=100): 可变位置函数(所谓的可变是指传参数量可变)Def func_name(*arg):    打包-->元组可变关键字函数    Dfe func_name(**kwarg):    打包--&g

Python基础(6)_函数

一 为何要有函数? 不加区分地将所有功能的代码垒到一起,问题是: 代码可读性差 代码冗余 代码可扩展差 如何解决? 函数即工具,事先准备工具的过程是定义函数,拿来就用指的就是函数调用 结论:函数使用必须是:先定义,后调用 python中函数定义方法: def test(x): "The function definitions" x+=1 return x def:定义函数的关键字 test:函数名 ():内可定义形参 "":文档描述(非必要,但是强烈建议为你的函数

python 全栈 python基础 (十三)匿名函数 与 内置函数

一.匿名函数  1.定义: 匿名函数顾名思义就是指:是指一类无需定义标识符(函数名)的函数或子程序. 2.语法格式:lambda 参数:表达式 lambda语句中,开头先写关键字lambda,冒号前是参数,可以有多个,用逗号隔开:冒号右边的为表达式,需要注意的是只能有一个表达式.由于lambda返回的是函数对象(构建的是一个函数对象),所以需要定义一个变量去接收.  3.注意点:lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值.lambda 函数不能包含命令,包含