"""
今日内容:
1、函数的嵌套定义及必包
2、global 与 nonlocal 关键字
3、开放封闭原则及装饰器
""" """
一、函数的嵌套定义及闭包
-- 在一个函数中定义另一个函数的过程叫做函数的嵌套定义 -- 为什么要使用函数的嵌套定义?
-- 在一个函数中要是用另一个函数中的变量,就在原函数中嵌套定义这个新函数
-- 但是嵌套定义后函数内部的函数就只能在函数的原函数的内部使用,在函数外部不能直接访问该函数
-- 如果想要访问新函数,可以将新函数作为返回值传递到函数的内部
-- 这样,在函数的外部重新定义一个与新函数重名的变量就可以像内部函数一样进行加()使用 -- 闭包(closure):在函数内部定义的,在函数外部也可以进行调用的函数就叫做闭包函数。
""" """
二、global 与 nonlocal 关键字
-- global 关键字
-- 当想要将函数内部的变量升级为全局变量时,就可以使用global关键字
-- 使用方法为:在函数内部需要升级变量作用域的变量上方加入 global 变量名
def fn1():
num = 10
-- 如果想要将num的作用域提升为全局,那么就需要在函数的上方加入 global关键字
def fn1():
global num
num = 10
-- 这样函数num的作用域就是全局了 -- nonlocal 关键字
-- 当只想要将嵌套函数内部的变量提升一个等级,那么就需要使用到nonlocal 关键字,但是使用nonlocal关键字使需要注意两个问题
-- 使用nonlocal关键字提升变量等级时,此关键字必须在父类函数中存在,不存在就会报错
-- 如果要提升变量等级,此变量所在的函数必须有父类函数,如果没有也会报错 -- global 与 nonlocal关键字的使用注意事项: -- 如果想要统一 outer 及 inner中的 num ,那么就将两个 num 都是用global进行声明,而不能使用nonlocal进行链式升级。
num = 0
def outer():
global num
num = 1
def inner():
global num
num = 10
print(num)
inner()
print(num)
outer()
print(num) """ """
三、开放封闭原则及装饰器
-- 开放封闭原则
-- 开放原则:可以为代码添加新的功能
-- 封闭原则:
-- 不能修改源代码
-- 不能修改调用方式 -- 装饰器
装饰器是一个满足开放封闭原则的闭包的应用 -- 多装饰器的加载顺序:
-- 先进后出,后进先出
"""
# 装饰器的推导:
"""
想要给原函数添加新功能,但是不能修改原函数及函数的调用方式
原函数:
def fn1():
print("插花") 需要添加的功能: 观赏 """ # 闭包函数的推导 """
def fn1():
num = 10 def fn2():
print(num)
""" # 第一种方法:将fn1的num作为返回值传递给外部,再用名字为num的变量进行接收 --> 这样只是有一个找了一个重名的变量,并不是原来的变量
# 第二种方法:使用global关键字将num变为全局变量,这样,如果全局变量中有num这个变量,会重新赋值
# 第三种方法:将函数fn2定义到函数fn1的内部,这样fn2就可以使用fn1的变量了 # 综上使用第三种方法进行验证
"""第一步:想要在一个函数内部使用另一个函数的内部变量 --> 将新函数放入到原函数的内部
def fn1():
num = 10
def fn2():
print(num)
-- 使用这种方法时,弊端就是不能在全局中调用fn2函数,只能在fn1中调用
""" """ 第二步:想要在全部中访问函数fn2:可以将fn2作为fn1函数的返回值,在外界接收后记性调用 def fn1():
num = 10
def fn2():
print(num)
return fn2 # res = fn1()
fn2 = fn1()
fn2() -- 使用这种方法可以将函数的返回值使用变量进行接收,变量可以使用任意合法的变量名接收,可以使用n,m等名字,也可以使用fn2进行接收
-- 当使用fn2进行接收时,此时使用fn2()就可以执行,跟直接调用原来的函数相同。这样fn2既可以使用num 又可以在外界进行调用。
-- 这个在函数内部定义的函数就叫做闭包函数(closure)
""" # 装饰器推导
"""第一步:在函数的内部调用原来的函数 def fn2():
print("观赏")
fn1() fn1 = fn2
fn1() # RecursionError: maximum recursion depth exceeded while calling a Python object -- 这样看似可以使用,但是在调用时会报错,原因是函数执行过程中,执行时先到 def fn2() --> fn1 = fn2 此时 fn1中内存地址与fn2中相同 -->
fn1()实际上就是运行fn2() --> 进入到fn2函数内部 --> 打印 插花 --> 运行fn1(),但是此时fn1=fn2,还是会调用fn2函数 --> 死循环 """ """第二步:对第一步进行更新,将fn1首先赋值给第三方变量temp,此时就不会进入死循环
temp = fn1 def fn2():
print("观赏")
temp() fn1 = fn2
fn1() -- 此时就是装饰器
-- 但是此装饰器分为了三部分,temp = fn1 ,def fn2 ,fn1=fn2,如果在三部分中间不小心对temp进行了重新赋值,就会破坏这个装饰器
-- 为了时装饰器更加的统一,需进行进一步进化
""" """第三步:将装饰器的三部分进化为两部分
-- 由于fn2函数的内部需要使用temp,此时可以将这两部分封装为一个函数
def outer():
temp = fn1
def fn2():
print("观赏")
temp()
return fn2 fn1 = outer()
fn1() -- 此时,装饰器已经进一步完善,但是如果fn1是有参数及返回值的呢?需要将函数的参数及返回值传递到装饰器内部
""" """第四步:给原函数添加参数 def fn1(name):
print("插花%s"%name) def outer():
temp = fn1 def fn2(name):
print("观赏")
temp(name) return fn2 fn1 = outer()
name = input("花: ")
fn1(name) -- 函数还是有可能也有返回值,需要将返回值传递到装饰器的内部
""" """第五步:给装饰器传递返回值 def fn1(name):
print("插花%s"%name)
return name def outer():
def fn2(name):
print("观赏")
res = temp(name)
return res
return fn2 fn1 = outer()
name = input("花: ")
print(fn1(name)) -- 此时,函数既有参数也有返回值了,已经无限接近于完美了,但是还有一个小问题,这个装饰器只能给固定的一个函数fn1使用(添加新功能),但是如果想给
其它的函数也使用这个装饰器呢? """ """第六步:将装饰器变成可以通用的装饰器
-- 如果想要将装饰器变为通用的装饰器,此时有两个方面需要修改,一个是被装饰的函数本身,另一个是函数的参数列表不固定 def fn1(name):
print("插花%s"%name)
return name def outer(func):
def fn2(*args,**kwargs):
print("观赏")
res = func(*args,**kwargs)
return res
return fn2 fn1 = outer(fn1)
name = input("花: ")
print(fn1(name)) -- 函数本身的变化可以将函数通过outer传入
-- 函数的参数列表的变化,可以使用可变长形参进行传递(*args,**kwargs) """ """
根据上述步骤,可以总结一个装饰器的公式: def outer(func):
def inner(*args,**kwargs):
pass # 要添加的代码块
res = func(*args,**kwargs)
pass # 需要添加的功能代码
return res
return inner """ """第七步:在python中提供了一种语法糖,可以将整个装饰器与被装饰的函数统一为一个整体
-- 这种语法就是使用 @装饰器名称 添加到被装饰函数的上方
-- 使用这种语法糖需要将装饰器函数写到被装饰函数的上方 """

day13 闭包及装饰器的更多相关文章

  1. python闭包与装饰器

    转自小马哥: 闭包和装饰器充分体现了Python语法糖的优雅感觉. 在本文中,我们的实验要完成两个工作,一个是加法,一个是累计调用加法的次数,最普通的Python程序可以这么写: def valida ...

  2. python之闭包与装饰器

    python闭包与装饰器 闭包 在函数内部定义的函数包含对外部的作用域,而不是全局作用域名字的引用,这样的函数叫做闭包函数. 示例: #-------------------------------- ...

  3. Python编程四大神兽:迭代器、生成器、闭包和装饰器

    生成器 生成器是生成一个值的特殊函数,它具有这样一个特点:第一次执行该函数时,先从头按顺序执行,在碰到yield关键字时该函数会暂停执行该函数后续的代码,并且返回一个值:在下一次调用该函数执行时,程序 ...

  4. python中的闭包和装饰器

    重新学习完了函数,是时候将其中的一些重点重新捋一捋了,本次总结的东西只有闭包和装饰器 1.闭包 闭包是python函数中的一个比较重要功能,一般闭包都是用在装饰器上,一般学完闭包就会去学习装饰器,这俩 ...

  5. python 闭包和装饰器

    python 闭包和装饰器 一.闭包闭包:外部函数FunOut()里面包含一个内部函数FunIn(),并且外部函数返回内部函数的对象FunIn,内部函数存在对外部函数的变量的引用.那么这个内部函数Fu ...

  6. Python核心编程的四大神兽:迭代器、生成器、闭包以及装饰器

      生成器 生成器是生成一个值的特殊函数,它具有这样的特点:第一次执行该函数时,先从头按顺序执行,在碰到yield关键字时该函数会暂停执行该函数后续的代码,并且返回一个值:在下一次调用该函数执行时,程 ...

  7. 21.python中的闭包和装饰器

    python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). 以下说明主要针对 python ...

  8. Python 中的闭包与装饰器

    闭包(closure)是函数式编程的重要的语法结构.闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性. 如果在一个内嵌函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内嵌函数 ...

  9. 关于python的闭包与装饰器的实验

    首先看闭包,在嵌套函数内添加返回值,可以通过外部函数读取内部函数信息 #encoding=utf-8 #闭包应用 #先定义闭包函数,并使用 def outer(func): def inner(): ...

随机推荐

  1. 使用 canvas 画图时图像文字模糊的解决办法

    最近在使用 canvas 画图的时候,遇到了图像文字模糊的问题,解决思路就是根据分辨率创建不同尺寸的画布.以下是创建高分辨率画布的代码: /** * 创建高分辨率画布 * @param w 画布宽 * ...

  2. 13 在 Django REST framework 善用 SerializerMethodField方法

    01-使用SerializerMethodField 来优化不必要的查询 class RepairQueueSerializer(serializers.ModelSerializer): # rq_ ...

  3. 如何用Eclipse创建一个JavaSwing的项目

    创建之前必须先给开发工具安装WindowBuilder插件(安装方法可自行百度) 方式一: 创建项目 new--other--WindowBuilder--SWT Designer----SWT/JF ...

  4. java前端js和框架内容知识和面试

    关于数据库知识和面试 关于JAVA知识和面试 一.多个ajax请求执行顺序问题 若点击一个操作内,发送两个ajax请求,其中一个请求会不会等待另一个请求执行完毕之后再执行? 不会,这两个异步请求会同时 ...

  5. Flask自定义转换器,实现路由匹配正则表达式参数

    Flask框架动态路由实现参数传递和Django框架有类似之处,但是相比于Django框架,Flask实现复杂的参数就需要自己自定义转换器来实现了,而不能向Django那样直接使用正则表达式 # 路由 ...

  6. webpack code splitting

    一.代码分割优化 const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin' ...

  7. PHP细节,empty,is_null,isset,if()

    以下内容转载自http://wuxinjie.github.io/php-04/ 从下表可知,empty与if()完全相反,is_null与isset完全相反 isset是语句,is_null是函数, ...

  8. Jenkins+Git+Maven搭建自动化构建平台

    http://blog.csdn.net/xlgen157387/article/details/50353317

  9. flex布局实例demo全解

    上篇文章介绍了Flex布局的语法,今天介绍常见布局的Flex写法. 你会看到,不管是什么布局,Flex往往都可以几行命令搞定. 我只列出代码,详细的语法解释请查阅<Flex布局教程:语法篇> ...

  10. 用ES6创建一个简单工厂模式

    1 什么是工厂模式? 工厂模式是用来创建对象的一种最常用的设计模式.我们不暴露创建对象的具体逻辑,而是将将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂.工厂模式根据抽象程度的不同可以分为:简 ...