zoukankan      html  css  js  c++  java
  • 函数进阶

    内容一览:

    动态参数 *args **kwargs
    名称空间(局部,全局,内置)
    作用域:全局作用域,局部作用域
    加载顺序与取值顺序
    内置函数:globals() locals()
    关键字: global nonlocal
    函数的嵌套(高阶函数)

    函数的初识:
    封装一个功能
    def 函数名():
    函数体

    函数的返回值:return
    1.结束函数
    2.返回给执行者值

    return ---> 返回 None
    return单个值 ---> 返回单个值
    return多个值 ---> 返回一个元组

    函数的参数:
    实参:
    1.位置参数——必须与形参角度的位置从左到右一一对应
    2.关键字参数——必须一一对应,可以不按顺序
    3.混合参数——位置参数必须在关键字参数前面

    形参:
    1.位置参数——必须与实参角度的位置从左到右一一对应
    2.默认参数——必须一一对应
    3.动态参数——*args, **kwargs


    1 # 动态参数 *args **kwargs
    2 
    3 def func(*args, **kwargs): # 这句表示在函数的定义时,*表示函数的聚合
    4     print(args)
    5     print(kwargs)
    6 func(1, 2, 3, 4, 5, "alex", name="taibai", sex="")
    7 
    8 # (1, 2, 3, 4, 5, 'alex')
    9 # {'name': 'taibai', 'sex': '男'}
     1 # *的魔性用法
     2 
     3 # 写一个函数,可以传入多个列表,把列表里的所有元素一个一个添加到args里面
     4 
     5 def func(*args, **kwargs):
     6     print(args)
     7 set = func(*[1, 2, 3], *(1, 2, 3), *"askj")     # 函数调用时,*代表打散
     8 print(set)
     9 
    10 # (1, 2, 3, 1, 2, 3, 'a', 's', 'k', 'j')
    11 # None
    12 
    13 
    14 def func(**kwargs):
    15     print(kwargs)
    16 func(**{"name": "alex"}, **{"age": 16})
    17 
    18 # {'name': 'alex', 'age': 16}
    19 
    20 
    21 def func(*args, **kwargs):
    22     print(args)
    23     print(kwargs)
    24 func(*[1, 2, 3], *"adj", **{"name": "alex"}, **{"age": 16})
    25 
    26 # (1, 2, 3, 'a', 'd', 'j')
    27 # {'name': 'alex', 'age': 16}
    28 
    29 # 总结
    30 # 在函数定义时,* **代表聚合
    31 # 在函数调用时,* **代表打散
     1 # 特殊用法
     2 a, b, *args = [i for i in range(20)]
     3 print(a, b, args)
     4 # 0 1 [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
     5 
     6 # 小 bug
     7 
     8 def func(*args, **kwargs):
     9     print(args)
    10     print(kwargs)
    11 func(*[1, 2, 3], *"adj", **{1: "alex"}, **{"age": 16})
    12 
    13 # 这里如果字典里的key是数字就不行,必须是字符串
    14 # 比如这样就可以
    15 
    16 def func(*args, **kwargs):
    17     print(args)
    18     print(kwargs)
    19 
    20 func(*[1, 2, 3], *"adj", **{"name": "alex"}, **{"age": 16})
    21 
    22 # (1, 2, 3, 'a', 'd', 'j')
    23 # {'name': 'alex', 'age': 16}
     1 # 形参的顺序问题
     2 # 下面这些的顺序怎么排?
     3 # a, b, c, sex="男", *args, **kwargs
     4 
     5 # 位置参数一定要在默认参数的前面
     6 def func(a, b, sex=""):
     7     print(a)
     8     print(b)
     9     print(sex)
    10 func(1, 2, sex="") # 这里也可以把 sex= 去掉
    11 
    12 # 1
    13 # 2
    14 #
    15 
    16 
    17 def func(a, b, *args, sex=""):
    18     print(a)
    19     print(b)
    20     print(args)
    21     print(sex)
    22 func(1, 2, "", "非男")
    23 
    24 # 1
    25 # 2
    26 # ('女', '非男')
    27 #
    28 
    29 
    30 def func(a, b, *args, sex=""):
    31     print(a)
    32     print(b)
    33     print(args)
    34     print(sex)
    35 func(1, 2, "", "非男", sex="")
    36 
    37 # 1
    38 # 2
    39 # ('女', '非男') # 都传递给了args
    40 #
    41 
    42 
    43 def func(a, b, *args, sex="", **kwargs):
    44     print(a)
    45     print(b)
    46     print(args)
    47     print(sex)
    48     print(kwargs)
    49 func(1, 2, "", "非男", sex="", name="alex")
    50 
    51 # 1
    52 # 2
    53 # ('女', '非男')
    54 #
    55 # {'name': 'alex'}
    56 
    57 
    58 # 总结(很重要):
    59 # 形参的排序 ---> 位置参数 > *args > 默认参数 > **kwargs
    程序开始运行时是逐行解释,从上往下运行
    遇到了初始化对象命令时,在内存中存放一个变量与值的对应关系的空间,称为全局名称空间

    def func():
    sex = ""
    func()

    程序走到这个函数时,看到函数的定义,会把函数名与函数体的对应关系在内存中存放一个命名空间,里面没有任何东西
    遇到函数调用时,会在内存中再开辟一个临时的名称空间,存放的是函数体里面的变量与值(sex=""),该临时名称空间会随着函数的结束而消失
    因此在 func() 下一行加 print(sex)时没有结果
    因为函数已经结束,这个临时名称空间(局部名称空间)已经消失了

    全局名称空间:存放的是py文件中变量与值的对应关系
    局部名称空间:临时存放的是函数体里面的变量与值的对应关系
    内置名称空间:内置函数,关键字等等,比如 print(), input()
    作用域,分为全局作用域与局部作用域
    全局作用域:全局名称空间,内置名称空间
    局部作用域:局部名称空间

    加载顺序——加载到内存的顺序
    内置名称空间 ---> 全局名称空间 ---> 局部名称空间
    解释器加载到内存中才能写代码,这个时候内置函数已经一起加进内存去了,所以内置名称空间是最先加载的
    接下来运行程序,肯定是先加载全局名称空间,遇到函数时才加载局部名称空间
     1 # 取值顺序(就近原则)
     2 
     3 def func():
     4     name = "flash"
     5     print(name)
     6 func()    # flash
     7 
     8 name = "alex"
     9 def func():
    10     name = "flash"
    11     print(name)
    12 func()    # flash
    13 # 这里 print(name)是先打印里面的name 对应的变量——即所谓的就近原则
    14 
    15 name = "alex"
    16 def func():
    17     # name = "flash"
    18     print(name)
    19 func()    # alex
    20 # 这时局部名称空间里已经没了name这个变量对应的值,所以它就在外面找
    21 
    22 input = "alex"
    23 def func():
    24     print(input)
    25 func()    # alex
    26 
    27 # 因此取值顺序是
    28 # 局部名称空间 --> 全局名称空间 --> 内置名称空间
     1 # LEGB 原则,也是就近原则
     2 
     3 name = "三包"
     4 def func():
     5     name = "alex"
     6     # print(name)
     7     def inner():
     8         name= "barry"
     9         print(name)
    10     inner()
    11 # print(name)
    12 func()
    13 
    14 # 因此这个程序运行结果是 barry
    15 # 如果把 print(name) 放在 "alex" 下面,结果是 alex
    16 # 如果把 print(name) 放在 func() 上面, 则打印 三包
     1 # 内置函数: globals() locals()
     2 
     3 name = "alex"
     4 age = 16
     5 
     6 def func():
     7     name = "barry"
     8     age = 18
     9 
    10 print(globals())
    11 print(locals())
    12 
    13 # {'__name__': '__main__',..., 'name': 'alex', 'age': 16}
    14 
    15 # {'__name__': '__main__',..., 'name': 'alex', 'age': 16}
    16 
    17 # globals() 打印结果是一个字典,里面内容很多,包含全局作用域的所有内容
    18 # locals() 返回的是当前作用域的内容
    19 
    20 name = "alex"
    21 age = 16
    22 
    23 def func():
    24     name = "barry"
    25     age = 18
    26     print(globals())
    27     print(locals())
    28 func()
    29 
    30 # {'__name__': '__main__',..., 'name': 'alex', 'age': 16}
    31 
    32 # {'age': 18, 'name': 'barry'}
    33 # 这里发现 locals() 的结果出来了,因为在当前作用域有内容
    34 
    35 name = "alex"
    36 age = 16
    37 
    38 def func():
    39     name = "barry"
    40     age = 18
    41     def inner():
    42         print(globals())
    43         print(locals())
    44     inner()
    45 func()
    46 
    47 # {'__name__': '__main__',..., 'name': 'alex', 'age': 16}
    48 
    49 # {}
    50 
    51 # 注意刚才说的 locals()返回的是当前作用域的内容,而这里的“当前”什么也没有,因此打印空字典
    52 
    53 # 无论是加载顺序还是取值顺序都是单向不可逆的
     1 # 高阶函数
     2 # 记住一点:代码是从上往下执行的!!!
     3 # 注意观察下面几个函数的对比
     4 
     5 def func1():
     6     print(111)
     7 
     8 def func2():
     9     print(222)
    10     func1()
    11 
    12 def func3():
    13     print(333)
    14     func2()
    15 print(555)
    16 func3()
    17 print(666)
    18 
    19 # 555
    20 # 333
    21 # 222
    22 # 111
    23 # 666
    24 
    25 # 先是执行 print(555)
    26 # 然后执行函数
    27 # 先执行 func3
    28 # 执行完后要等 func3 里面的 func2执行
    29 # func2 执行后要等里面的 func1 执行
    30 # 最后才执行 print(666)
    31 
    32 def func1():
    33     print(1)
    34     def inner():
    35         print(2)
    36         def inner2():
    37             print(3)
    38     print(4)
    39     inner()
    40     print(5)
    41 func1()
    42 
    43 # 1
    44 # 4
    45 # 2
    46 # 5
    47 
    48 # 注意顺序
    49 # 先执行 print(1)
    50 # 再执行 print(4)
    51 # 再执行 innner(),这里只执行 print(2),不执行 inner2()
    52 # 最后执行 print(5)
     1 # global nonlocal
     2 # global 可以在局部声明一个变量
     3 
     4 def func():
     5     name = "alex"
     6 func()
     7 print(name)
     8 
     9 # 报错,找不到 name,因为 name 在局部名称空间
    10 
    11 def func():
    12     global name
    13     name = "alex"
    14 func()
    15 print(name)    # alex
    16 
    17 # 这里 global name 相当于表示不仅在局部有这个变量对应的值,全局也有(同步)
    18 
    19 age = 46
    20 def func():
    21     global name
    22     name = "alex"
    23     name = "barry"
    24 func()
    25 print(name)    # barry
    26 
    27 # 在局部改变了这个变量对应的值的话,全局也会同步改变
    28 # 这里注意函数执行结束后,全局的变量指向的值在内存中还存在
    29 
    30 age = 46
    31 name = "xxx"
    32 def func():
    33     global name
    34     name = "alex"
    35     name = "barry"
    36 func()
    37 print(name)  # barry
    38 
    39 # 这里相当于局部可以操控全局
    40 
    41 age = 46
    42 name = "xxx"
    43 def func():
    44     global name
    45     name = "alex"
    46     name = "barry"
    47 func()
    48 name = "aaa"
    49 print(name)
    50 
    51 count = 1
    52 def func():
    53     count += 1
    54 func()
    55 
    56 # 局部作用域不能对全局作用域的变量进行修改,只能引用
    57 
    58 count = 1
    59 def func():
    60     global count
    61     count += 1
    62 func()
    63 print(count)
    64 # 说明可以通过设置global就可以修改
    65 
    66 # global用法总结:
    67 # 可以局部作用域声明一个全局变量
    68 # 局部作用域不能对全局作用域的变量进行修改,只能引用,但可以通过设置global修改
     1 # nonlocal: 只在python3x中存中
     2 # 子级对父级的操控
     3 
     4 # 不能操控全局变量
     5 name = "alex"
     6 def func():
     7     nonlocal name
     8     print(name)
     9 func()
    10 
    11 # 内存函数可以引用外出函数的变量
    12 def wrapper():
    13     name = "alex"
    14     def inner():
    15         print(name)
    16     inner()
    17 wrapper()
    18 
    19 # 内层函数只能引用外层函数的变量,不能改变
    20 def wrapper():
    21     name = "alex"
    22     def inner():
    23         name += "b"
    24     inner()
    25 wrapper()
    26 # 报错
    27 
    28 # 非要修改,只能用nonlocal
    29 def wrapper():
    30     name = "alex"
    31     def inner():
    32         nonlocal name
    33         name += "b"
    34         print(name)
    35     inner()
    36 wrapper()
    37 
    38 
    39 def wrapper():
    40     name = "alex"
    41     def inner():
    42         nonlocal name
    43         name += "b"
    44         print(name)
    45     print("1", name)
    46     inner()
    47     print("2", name)
    48 wrapper()
    49 
    50 # 先执行 print("1", name)
    51 # 再执行 inner(),name变量指向的值已经变为 alexb
    52 # 最后执行 print("2", name)时,因为前面已经执行 inner(),因此从第二步开始,往下所有的name变量指向的值都变成了 alexb
  • 相关阅读:
    【校招内推】2022届菜鸟网络Java内推
    Git版本管理流程与规范-生活圈
    Jenkins:Git拉取代码版本不对
    java html2image
    CentOS 7.6构建MySQL PXC高可用集群
    你可能不知道的Docker资源限制
    Docker镜像源修改
    centos7.2安装docker(二进制离线安装)
    ansible playbook 配置计划任务
    NFS服务的用户身份映射
  • 原文地址:https://www.cnblogs.com/shawnhuang/p/10198125.html
Copyright © 2011-2022 走看看