zoukankan      html  css  js  c++  java
  • day13

    复习

    '''
    1.函数对象:函数名 => 存放的是函数的内存地址
    1)函数名 - 找到的是函数的内存地址
    2)函数名() - 调用函数 => 函数的返回值 eg:fn()() => fn的返回值一定是函数
    使用:
    1)直接被其他变量接收 - 将函数的内存地址直接给其他变量 => 被赋值的变量也是函数对象
    2)可以作为函数的参数 - 函数的形参接收到的实参是函数对象 => 形参被赋值后也是函数对象
    3)可以作为函数的返回值 - 用变量在外界调用并接受这个函数的值 => 用来接收的变量也是函数对象
    4)可以作为容器对象的成员 - 可以作为list、dict等的成员 => 函数对象作为成员的那个成员被取出就是函数对象
    def add(n1, n2): return n1 + n2
    method_map = {
    'add': add

    2.名称空间与作用域
    # LEGB

    # 名称空间:名字与地址的对应关系
    内置:系统级,一个
    全局:文件级,多个
    局部:函数级,多个
    加载顺序: 内置 > 全局 > 局部

    # 作用域:名字起作用的范围
    局部:只在局部可见
    嵌套:在外层函数的局部与内部函数的局部可见
    全局:在当前文件的任意位置可见
    内置:在所有位置可见
    查找顺序:局部 > 嵌套 > 全局 > 内置

    3.函数的嵌套定义:在函数的内部定义函数

    今日内容

    1.函数的嵌套定义

    2.global、nonlocal关键字

    3.闭包及闭包的运用场景

    4.装饰器

    函数的嵌套定义

    # 概念:在一个函数的内部定义另一个函数

    # 为什么要有函数的嵌套定义:
    # 1)函数fn2想直接使用fn1函数的局部变量,可以讲fn2直接定义到fn1的内部,这样fn2就可以直接访问fn1的变量
    # 2)函数fn2名字就变成fn1的局部变量了,正常只能在fn1中使用,想在外部使用,可以讲fn2函数对象作为fn1函数的返回值
    # 3)在外部也用同名的变量fn2来接收fn1函数的执行结果(fn1函数的返回值),那么fn2也就是可以在外部被调用

    global关键字

    # 作用:将局部的变量提升为全局变量
    # 1.全局没有同名变量,直接提升局部变量为全局变量
    # 2.有同名全局变量,就是统一全局与局部的同名变量
    # -- 如果局部想改变全局变量的值(发生地址的变化),可以用global声明该变量

    # num = 888
    def fn1():
    global num
    # print(num)
    # 没有global修饰,num就是自己局部的变量
    # 有global修饰,num就是全局的num,全局中只能出现一个num,如果出现了值的改变,大家一起变
    num = 666
    def fn2():
    print(num) # 666
    fn1()
    fn2()

    nonlocal关键字

    # 作用:将局部的变量提升为嵌套局部变量
    # 1.必须有同名嵌套局部变量,就是统一嵌套局部与局部的同名变量
    # -- 如果局部想改变嵌套局部变量的值(发生地址的变化),可以用nonlocal声明该变量

    def outer():
    num = 888
    def inner():
    nonlocal num
    num = 666
    print(num) # 666
    inner()
    print(num) # 666
    outer()

    开放封闭原则

    # 开放封闭原则:在不修改源代码与调用方式的情况下为函数添加新功能 *****
    # 开放:有些事,你可以干 - 拓展功能
    # 封闭:有些事,你干不了 - 两个原则
    # 1.不能修改源代码 - 1.无权修改 2.功能不特有 3.修改的位置多个,需要一一修改
    # 2.不能修改原函数的调用方式 - 修改调用方式的弊端,原项目的所有函数调用都要修改

    装饰器

    # 装饰器:满足开放封闭原则的一个闭包应用

    # @outer语法来调用outer,规定传入被装饰的函数对象,所以参数固定为一个,接受被装饰的函数对象
    def outer(func):
    # 不能确定被装饰的函数的参数:来者不拒,用可边长来接受
    def inner(*args, **kwargs):
    pass # 新功能位
    res = func(*args, **kwargs) # 解压带给原功能
    pass # 新功能位
    return res
    return inner


    # 使用装饰器(outer),得到新功能(inner)

    # 用被装饰的函数名去接受装饰器的执行结果,调用装饰器时传入被装饰的函数对象
    @outer # fn = outer(fn) = inner
    def fn(): pass


    # 表面感觉调用的是原函数,本质调用的是闭包(inner),使用fn调用和fn定义及inner需要参数统一
    fn()

    一个函数被多次装饰


    def outer(func):
    def inner(*args, **kwargs):
    res = func(*args, **kwargs)
    return res
    return inner


    def check_user(func):
    def inner(*args, **kwargs):
    # 账号的验证功能
    user = args[0] # type: str
    if not (user.isalpha() and len(user) >= 3):
    print('账号不合法')
    return False

    res = func(*args, **kwargs)
    return res
    return inner

    def check_pwd(func):
    def inner(*args, **kwargs):
    pwd = args[1]
    if len(pwd) < 3:
    print('密码不合法')
    return False

    res = func(*args, **kwargs)
    return res
    return inner

    def format_return(func):
    def inner(*args, **kwargs):
    res = func(*args, **kwargs)
    if res:
    return '登录成功'
    return '登录失败'
    return inner


    # 登录的原功能

    @format_return
    @check_user
    @check_pwd
    def login(user, pwd):
    if user == 'owen' and pwd == '123':
    return True
    return False

    user = input('user: ')
    pwd = input('pwd: ')
    res = login(user, pwd)
    print(res)

    # 执行过程:调用login => 进入第一个装饰器(format_return)的inner => 进入第二个装饰器(check_user)的inner => 进入第三个装饰器(check_pwd)的inner => 开始返回,从第三个返回到第二个再返回到第一个,最后返回到外界调用的位置

  • 相关阅读:
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1131 Subway Map (30 分)
    PAT 甲级 1131 Subway Map (30 分)
    AcWing 906. 区间分组 区间贪心
    AcWing 907. 区间覆盖 区间贪心
  • 原文地址:https://www.cnblogs.com/1624413646hxy/p/10787244.html
Copyright © 2011-2022 走看看