• python-函数作用域闭包


    1、拆包补充,首先先看一段代码:

    def func(*args, **kwargs):
        print(args)
        print(kwargs)
    
    
    list1 = [1, 2, 3, 4, 6, 8]
    func(list1, 100)  #([1, 2, 3, 4, 6, 8], 100)  {}
    func(*list1, 100) # (1, 2, 3, 4, 6, 8, 100)  {}
    func(*list1, 100, a=1)  # (1, 2, 3, 4, 6, 8, 100)  {'a': 1}
    dict1 = {'a': 10, 'b': 20, 'c': 30}
    func(list1, 100, dict1)
    # ([1, 2, 3, 4, 6, 8], 100, {'a': 10, 'b': 20, 'c': 30})
    # {}
    func(*list1, 100, dict1)
    # (1, 2, 3, 4, 6, 8, 100, {'a': 10, 'b': 20, 'c': 30})
    # {}
    func(*list1, 100, **dict1)
    # (1, 2, 3, 4, 6, 8, 100)
    # {'a': 10, 'b': 20, 'c': 30}

    **dict1 在函数调用的时候表示拆包,会将字典中内容拆成关键字参数的形式

    def func(a,b,c):
        list1 = [a,b,c]
        print(list1)
    dict1={'a':10,'b':20,'c':30}
    func(**dict1)  # [10, 20, 30]

    2、函数之间的调用

    books = ['红楼梦','西游记','水浒传','三国演义']
    
    def show_books():
        print('-----图书馆书籍如下:-------')
        for index,book in enumerate(books):
            print('{}:{}'.format(index+1,book))
    
    def add_books(book_name):
        if book_name:
            books.append(book_name)
            # 确认是否成功
            show_books()
            print('添加成功')
        else:
            print('书籍不能为空!')
    
    # 添加图书
    add_books('斗破苍穹')

    3、返回值:

      1》如果函数没有返回值则默认的返回值是None

      2》如果在函数中添加返回值,要通过return关键字

        return关键字的作用:

          1-返回return后面值

          2-结束方法(函数)

            break ---结束循环

            return----出现在函数,表示结束函数

          3-return可以单独使用,返回值是None

            python独有的

             return a,b,c    ------  (a,b,c)

      补:return后面可以是一个参数       接收的的时候x = add(1,2)

        return后面也可以是多个参数,如果是多个参数则底层会将多个参数先放在一个元组中,将元组作为整体返回。

        接收的时候也可以是多个:return 'hello','world'          x,y = ('hello','world')       x = 'hello'  y = 'world'

    list1 = [5,5,6,8,9,1]
    # 找到最大值
    def find_max(list1):
        if isinstance(list1,list):
            max1 = list1[0]
            for i in list1:
                if i >max1:
                    max1=i
            return max1
        
    m = find_max(list1)
    print(m)

      找到最大值,最大值所在的下标位置。

    list1 = [5,5,6,8,9,1]
    # 找到最大值
    def func(list1):
        if isinstance(list1,list):
            max1 = list1[0]
            max_index = 0
            for index,i in enumerate(list1):
                if i >max1:
                    max1=i
                    max_index = index
            # 返回结果
            return max1,max_index
    
    m = func(list1)
    print(m)  # (9, 4)

    4、函数的作用域:LEGB

    local  局部的  函数的本地变量

    locals()   在函数中使用,获取的是当前函数的局部变量们,将函数中的局部变量放到字典中

    enclosing  嵌套的  两层函数

    def func():
        a = 10     ------内层函数的enclosing
        def inner_func():
            print(a)
        inner_func()

    global  关键字------ 在函数中对全局变量进行声明而使用的

    globals()    用在函数的外层,获取全局的变量(系统的默认产生变量+自定义的变量)

    nonlocal    关键字  内层函数中想修改外部函数中变量

    builtins  系统内置、所有py文件执行的时候都会加载内置模块

    作用域的使用:

      全局的:

      books[]

      number = 10

      在函数中使用的时候:

      因为books是可变类型,所以可以省略global的声明

      因为number是不可变类型,所以在函数中如果想修改则必须添加global的声明

    ----------------------------------------------------------------------------------------------------------

    number = 10 ---》 全局
    
    def func():
        number = 0  # 局部变量
        print(number)
        number += 5  ---> 此时只能在局部变量上+5
    
    func()
    print(number)  ---》 10
    number = 10
    
    def func():
        # 如果想修改全局的变量number,必须要明确声明
        global number   ----> 明确声明以下使用的number是全局的number
        print(number)  # Unresolved reference 'number'  报错 只有局部变量才有更改“权限”,但是此时number不是局部的
        number += 5
    
    
    func()
    print(number)   ---》 15
    number = 10
    
    def func():
        global number
        print(number)    ---》10
        number = 9  # 相当于对全局变量number=10 的修改
        number += 5
    
    func()
    print(number)---》14

    对于可变类型的话:

    # 全局变量
    books = ['红楼梦', '西游记', '水浒传', '三国演义']
    number = 10
    
    
    def func():
        # books = []
        books.append('斩龙')  # ----> 因为books是可变类型,所以可以省略global的声明
        print(books)
        global number   # -----> 因为number是不可变类型,所以在函数中如果想修改则必须添加global的声明
        number += 8
    
    
    func()  #['红楼梦', '西游记', '水浒传', '三国演义', '斩龙']
    print(books)  # ['红楼梦', '西游记', '水浒传', '三国演义', '斩龙']
    print(number)  #  18

     5、搜索变量的规则是:

      1》如果有内部函数,先找内部函数自身的变量

      2》如果内部函数自身没有变量,则找外部函数的变量

      3》如果外部函数也不存在此变量则找全局

      4》如果全局也没有此变量则找builtins

      5》如果内部builtins也没有则报错

    a = 100
    b = 0
    def func(b):
        a=10
        def inner_func(c):
            # global b
            # b = 1
            nonlocal b
            c = a +b +c
            b = c
            print('c:',c)
            print('b:',b)
        print('a:',a)
        print('b:',b)
    
        inner_func(5)
    
    # 调用外部函数
    func(8)
    print(a)
    print(b)

    6、闭包:

      1》在一个函数中定义了另一个函数

      2》内层函数使用了外层函数的变量

      3》返回值是内层函数

      闭包的缺点:作用域没有那么直观          因为变量不会被垃圾回收所以会有一定的内存占用问题

      闭包作用:1.可以使用同级的作用域  2.读取其他元素的内部变量  3.延长作用域

      总结:

      闭包优化了变量,原来需要类对象完成的工作,闭包也可以完成。

      由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存

      闭包的好处,使代码简洁,便于阅读代码。

      闭包是理解装饰器的基础。

    def out_func(n):
        a = 10
        def inner_func():
            r = a + n
            print('r的值:',r)
        print(locals())
        return inner_func
    
    result = out_func(2)
    result()  #  r的值: 12

    7、函数作为参数使用的问题

      参数可以是str   int    bool   float   list   tuple   set   dict

    def A():
        print('hello world!')
    
    def func2(f):  # f = A的地址
        print('---->', f)
        f()
        print('---->over')
    
    func2(A)
    
    def func3(f):
        print('----->start:', f)
    
        def inner_func():
            print('-----》inner_func')
            f()
    
        print('----->end')
        return inner_func
    
    result = func3(A)
    print(result)
    result()

    8、装饰器:

      功能:1》引入日志  2》函数执行时间统计  3》执行函数前预备处理  4》执行函数后清理功能

         5》权限校验等场景  6》缓存

      注:写代码要遵循开放封闭的原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,他规定了已经实现的功能代码不允许被修改,但可以被拓展。

        开放:对拓展开放

        封闭:已实现的功能代码块

    # 1、定义函数,闭包的原则+函数作为参数   装饰器函数
    def func(f):
        print('******************1')
        def wrapper():
            print('装饰前。。。。验证是否登录')
            f()
            print('装饰后。。。。')
        print('-----------------2')
        return wrapper
    
    # 2、功能函数
    @func # 1.调用func函数  2.执行函数体内容   3.加载内部函数    4.返回内部函数wrapper 5.buy_ticket接收了func的返回值,
    def buy_ticket():
        print('我可以买票去看:雷火英雄')
    
    # 3、买票
    buy_ticket()

    例二:

    # 定义装饰器函数
    def decorator(func):  # func = house
        def wrapper():
            func()  # 此时的func就是原house()
            print('刷漆')
            print('铺地板')
            print('买家具')
            print('可以住.....')
    
        return wrapper
    
    
    @decorator
    def house():
        print('空的毛坯房...')
    
    
    house()
    一路独行,遇见最好的自己!!!
  • 相关阅读:
    如何使用robots.txt及其详解
    有序列表
    前端开发大众手册(包括工具、网址、经验等)
    转载:Tim O'Reilly与John Battelle谈即将开幕的Web
    转载:iframe全跨域高度自适应解决方案
    javascript 学习笔记
    【C#文件夹锁】C#文件夹加锁小工具
    Pro Silverlight 5 in C# 分享
    在Winform窗体中使用WPF控件(附源码)
    【C#文件锁】C#加密解密文件小工具
  • 原文地址:https://www.cnblogs.com/rungang/p/11282023.html
Copyright © 2020-2023  润新知