zoukankan      html  css  js  c++  java
  • 铁乐学Python_day10_函数2

    今天书接昨天的函数继续去学习了解:
    昨天说到函数的动态参数。

    1、函数的【动态参数】

    *args 动态参数,万能参数
    args接受的就是实参对应的所有剩余的位置参数,并将其放在元组( )中。
    
    def func(x, y, z, *args):
       print(x, y, z)
       print(args)
    
    func(1, 2, 'a', 'b', 'c', 34)
    
    1 2 a
    ('b', 'c', 34)
    
    **kwargs 动态参数
    将非位置对应的所有的关键字参数放到一个字典{  }中。
    (排除形参中位置参数对应的实参中的关键字参数)
    def func(x, y, z, *args, sex='男', **kwargs):
       print(x, y, z)
       print(args)
       print(sex)
       print(kwargs)
    
    func(1, 2, 'a', 'b', 'c', 34, m='yue', n=12, sex='女', p='r')
    
    1 2 a
    ('b', 'c', 34)
    女
    {'m': 'yue', 'p': 'r', 'n': 12}
    
    从形参的角度来看,它们的顺序应为:
    位置参数在最前,*args次之,
    默认参数因为形式上是关键字参数的式样故要排在*args后,而要在**kwargs之前。
    (位置参数,*args,默认参数,**kwargs)
    

    2、函数中【*和**的魔法运用】

    在函数的调用(执行)时,*加一个可迭代对象(列表,元祖,字符串,字典等)代表解包,
    (列表元祖打散成列表中的每个元素,字符串打散成每个字符,字典打散成每个键)
    并将元素一 一添加进args。

    如下例:

    def func(*args):
        return args
    l1 = [1, 2, 30]
    l2 = [1, 2, 33, 21, 45, 60]
    # 要求将l1 和 l2 转化成元祖,
    # 并且里面包含所有l1和l2的每一个元素,相同元素也得重复。
    # 解:
    tu = func(*l1, *l2)
    print(tu)
    
    (1, 2, 30, 1, 2, 33, 21, 45, 60)
    
    也可以简单理解成*是求可迭代对象的每一个元素。
    
    而在函数的定义时,*args代表的是聚合(打包成元祖)
    
    **运用只限于字典(因它存在有键值对,可两两对应上),
    同样在函数的调用执行时,**dict(一个字典对象),代表将字典所有的键值对放到kwargs字典里。
    (解包打散字典)
    
    例:
    def func(**kwargs):
        return kwargs
    dic = {'name':'tiele', 'age':18, 'hobby':'下棋'}
    dic2 = {'name2':'mao', 'age2':5, 'hobby2':'晒太阳'}
    # 字典的键得是唯一,如果两个字典同键虽然不同值,执行下面函数的**运用也会报错
    dic3 = func(**dic, **dic2)
    print(dic3)
    
    {'name': 'tiele', 'age': 18, 'hobby2': '晒太阳', 'hobby': '下棋', 'age2': 5, 'name2': 'mao'}
    
    
    在函数定义时,**kwargs代表的是聚合(成字典)
    

    3、全局命名空间、局部命名空间、内置命名空间

    名称空间:放置变量与对应的值(有的还有内存地址对应)的关系;

    全局命名空间,放置变量与对应的值(有的还有内存地址对应)的关系的名称空间。

    当执行函数的时候,内存开辟出一个临时名称空间(又叫局部命名空间),存放该函数内的变量与值的关系。
    随着函数的执行完毕,临时名称空间也随之关闭。

    内置名称空间,(python的内置函数),所有的内置函数等存储的空间。

    4、顺序与函数的嵌套

    加载顺序:
    内置名称空间--->全局名称空间--->(函数执行时)--->局部名称空间。

    取值顺序:
    刚好与加载顺序相反,优先级为:
    局部名称空间--->全局名称空间--->内置名称空间。

    函数的嵌套:
    函数在被调用的时候才执行;函数里面同样代码遵循从上至下依次执行;

    5、作用域

    作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。
    全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效。
    局部作用域:局部名称空间,只能在局部范围内生效。

    由作用域引申出两个函数方法globals()和locals()
    例:

    def func():
        a = 33
        b = 22
        print(locals())
        print(globals())
    
    func()
    c = 40
    print(locals())
    
    {'a': 33, 'b': 22}
    {'__name__': '__main__', '__spec__': None, 'func': <function func at 0x0000000000755488>, '__builtins__': <module 'builtins' (built-in)>,
     '__cached__': None, '__file__': 'E:/Python/day10/笔记.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000000000066E048>, 
    '__doc__': None, '__package__': None}
    
    {'__file__': 'E:/Python/day10/笔记.py',
     '__name__': '__main__', '__spec__': None, 
    '__builtins__': <module 'builtins' (built-in)>, 
    '__doc__': None, 'c': 40, 
    '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000000009AE048>, 
    '__cached__': None, '__package__': None, 
    'func': <function func at 0x0000000000D85488>}
    
    
    由上例可以看到,函数中locals存储的是{'a': 33, 'b': 22}
    

    因为它的作用域是在局部命名空间中,所以它存储的变量和值并不多,而在函数之外再打印的locals就不同了,它的作用域扩大了,但是不包括局部,所以里面的值里可以找到'c':40而找不到a,b的值。

    在函数中使用locals()方法可以很方便返回在这个临时命名空间作用域中所有的变量的值,呈字典返回,所以还是有它常用到的地方的。

    global关键字,nonlocal关键字:

    global:
    1、声明一个全局变量。
    2、在局部作用域想要对全局作用域的全局变量进行修改时,需要用到global(限于字符串,数字)。

    例:

    a = 2
    def func():
        a = 5
    func()
    print(a)  #这时候a返回的是2
    
    a = 2
    def func():
        global a
        a = 5
    func()
    print(a)  #使用了global后返回的是5
    
    注:对可变数据类型(list,dict,set)可以直接引用不用通过global。
    
    li = [1,2,3]
    dic = {'a':'b'}
    
    def change():
        li.append('a')
        dic['q'] = 'g'
        print(dic)
        print(li)
    change()
    print(li)
    print(dic)
    
    {'a': 'b', 'q': 'g'}
    [1, 2, 3, 'a']
    [1, 2, 3, 'a']
    {'a': 'b', 'q': 'g'}
    

    nonlocal:
      1、不能修改全局变量。
      2、在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。

    def add_b():
        b = 42
        def do_global():
            b = 10
            print(b)
            def dd_nonlocal():
                nonlocal b
                b = b + 20
                print(b)
            dd_nonlocal()
            print(b)
        do_global()
        print(b)
    
    add_b()
    
    10
    30
    30
    42
    

    【补充】:
    python是用命名空间来记录变量的轨迹的,命名空间是一个dictionary,键是变量名,值是变量值。
    当一行代码要使用变量 x 的值时,Python 会到所有可用的名字空间去查找变量,按照如下顺序:
    1)局部名字空间 - 特指当前函数或类的方法。
    如果函数定义了一个局部变量 x, 或一个参数 x,Python 将使用它,然后停止搜索。
    2)全局名字空间 - 特指当前的模块。如果模块定义了一个名为 x 的变量,函数或类,Python 将使用它然后停止搜索。
    3)内置名字空间 - 对每个模块都是全局的。作为最后的尝试,Python 将假设 x 是内置函数或变量。

    python的全局名字空间存储在一个叫globals()的dict对象中;
    局部名字空间存储在一个叫locals()的dict对象中。
    我们可以用print (locals())来查看该函数体内的所有变量名和变量值。

    end

  • 相关阅读:
    学习过程之python跳一跳
    OSError: [WinError -2147221003] 找不到应用程序: 'QR.png' 的解决方法
    易知大学 任务25 第一次爬虫与测试
    linux常用命令
    健身日志
    JavaScript JSON
    常用注解 开发SpringBoot项目
    网络基础
    jQuery MINI UI 学习之分页查询
    Springboot集成ActivitiModel提示输入密码
  • 原文地址:https://www.cnblogs.com/tielemao/p/8678447.html
Copyright © 2011-2022 走看看