zoukankan      html  css  js  c++  java
  • day10 参数args kwargs 作用域

    函数参数/作用域/args/kwargs

    1.参数

    1.1参数基本知识

    • 任意个数

    • 任意类型

      func("1",True)
      

    1.2位置传参(调用函数并传入参数)

    def func(a1,a2):
      pass
    func(1)#缺少位置参数
    func(1,2,3)#多了位置参数
    

    1.3关键字传参

    def func(a1,a2):
      pass
    func(a2=99,a1=2)#根据形参名字传入值
    

    1.4关键字传参和位置传参可以混合使用

    注意位置参数在前 关键字参数在后,总和参数个数要和函数参数个数相等

    def func(a1,a2,a3):
      pass
    func(1,a2=3,a3=9)#根据形参名字传入值
    func(a1=1,3,9)#报错 关键字参数在前
    func(1,a1=2,a3=9)#报错  a1得到多个值 
    func(1,a2=0,9)#报错  关键字在前
    

    1.5默认参数[定义]

    参照open()函数

    注意:如果默认值是可变类型
    def func(a1,a2=9)#a2可传可不传 
    		pass
    func(1,2)#给a2传新值 覆盖默认值
    func(1)#默认a2=9
    
    

    1.6 万能参数(*args)—>arguments 多个参数

    • args:接受n个位置参数

    • 可以接受任意类型参数,并转换为元组

    • 调用时候无*

      #args循环遍历每个位置参数 一个一个放入args中 并转换为元组
      def func(*args):  
          print(args)
      
      func(1)  # (1,)
      func(1, 2, 3)  # (1,2,3)
      func(1, 2, [1, 23], "True", "alex")
      func((1, 2, 3))
      # 该元组作为一个单元素传入   -->元组嵌套((1,2,3),))
      #(1,)
      # (1, 2, 3)
      # (1, 2, [1, 23], 'True', 'alex')
      # ((1, 2, 3),))
      
      
    • 调用时有:直接将后面的位置参数转换为元组

      def func(*args):  
          print(args)
      
      func(*(1, 2, 3))  # 打散传入元组 变成多个变量传入args -->(1,2,3)
      func(*[1, 2, 3])  # args原理是  循环遍历每个元素 添加到元组中(1,2,3)
      #(1, 2, 3)
      #(1, 2, 3)
      
    • 只能用位置传参

      
      def func(a1,*args,a2):
        pass
      func(1,2,3,4,a2=0)#a2只能关键字传参
      #a1=1 args=(2,3,4)
      
      

    1.7键值万能参数(**kwargs)

    • 接收任意个关键字参数

      def func(**kwargs):
        print(kwargs)
        
      func(k1=1,k2="gao")#kwargs={"k1":1,"k2":"gao"}
      
      
      
    • 调用时有*

      def func(**kwargs):
        print(kwargs)
      func(**{"k1":1,"k2":"gao"})#kwargs=kwargs={"k1":1,"k2":"gao"}
      
    • 调用时候无*

      def func(**kwargs):
        print(kwargs)
      func(k1=1,k2="gao")#kwargs={"k1":1,"k2":"gao"}
      
      
      
    • 只能用关键字传参

    • 综合应用

      def func(*args,**kwargs):
        print(args,kwargs)
      func(*[1,2,3],k1=2,k5=9,k19=999)#(1,2,3) {"k5":9,"k19":999}
      func(*[1,2,3],**{"k1":"1","k2":2})#(1,2,3){"k1":"1","k2":2}
      func(11,22,*[1,2,3],k11=333,k33="bb")#(11,22,1,2,3) {"k11":333,"k3":"bb"}
      
      #5.看代码写结果
      
      # def func(name,age=19,email='123@qq.com'):
      #     pass
      
      # a. 执行 func('alex') ,判断是否可执行,如可以请问 name、age、email 的值分别是?
      #可行 name=alex age=19 email=123@qq.com
      
      # b. 执行 func('alex',20) ,判断是否可执行,如可以请问 name、age、email 的值分别是?
      #可行  name:alex  age:20 email:123@qq.com
      
      # c. 执行 func('alex',20,30) ,判断是否可执行,如可以请问 name、age、email 的值分别是?
      #可行  name:alex  age:20 email:30
      
      # d. 执行 func('alex',email='x@qq.com') ,判断是否可执行,如可以请问 name、age、email 的值分别是?
      #可行  name:alex age:19 email:x@qq.com
      
      # e. 执行 func('alex',email='x@qq.com',age=99) ,判断是否可执行,如可以请问 name、age、email 的值分别是?
      #alex 99 x@qq.com
      
      # f. 执行 func(name='alex',99) ,判断是否可执行,如可以请问 name、age、email 的值分别是?
      #不可行  关键字参数在前  位置参数在后
      
      # g. 执行 func(name='alex',99,'111@qq.com') ,判断是否可执行,如可以请问 name、age、email 的值分别是?
      #不可行
      
      
      
    练习
    c. 请将执行函数,并实现让args的值为 ([11,22],33) 且 kwargs的值为{'k1':'v1','k2':'v2'}
    def func(*args,**kwargs):
        print(args)
        print(kwargs)
    val=func([11,22],33,k1="v1",k2="v2")
    val1=func(*[[11,22],33],k1="v1",k2="v2")
    #第一种:传入多个位置参数 循环遍历加入args后 变成元组 
    #第二种:类似强制转换方式   tuple([[11,22],33])将*后面的转换为元组
    
    ([11, 22], 33)
    {'k1': 'v1', 'k2': 'v2'}
    #————————————————————————————————————————————————————————
    ([11, 22], 33)
    {'k1': 'v1', 'k2': 'v2'}
    

    2.作用域

    2.1全局作用域

    2.1局部作用域

    2.3总结

    • 一个函数是一个作用域

      def func():
        x=9
        print(x)
      func()
      print(x)#报错
      
    • 作用域中查找数据规则:优先自己作用域查找,再去自己父级作用域查找,直到找到全局作用域为止

      x=10
      def func():
        x=9
        print(x)#9 
      func()
      print(x)#10
      
      • 注意:函数的调用顺序
      x = 10
      
      
      def func():
          x = 8
          print(x)  # 8
      
          def func2():
              x = 999
              print(x)  # 999
      
          print(x)  # 8
          func2()
      
      
      func()  # 执行 8 8 999
      
      
      
      
      #
      x = 10
      
      
      def func():
          x = 8
          print(x)  # 8
      
          def func2():
              x = 999
              print(x)  # 999
      
          print(x)  # 8
          func2()  #
          print(x)  # 8 
          #func2函数执行完毕后 内部局部变量x被销毁掉  所以不会对自己内部的变量进行重新赋值
      
      
      func()  # 执行8 8 999 8
      
      
    • 子作用域中只是读取或者修改【列表类型等可变类型】父级作用域的值,【默认】无法为父级的变量重新赋值 ,子作用域只是在自己内部重新开辟一块空间,为该变量赋值。但是通过添加global /nonlocal 关键字可以为父级的指定变量重新赋值

      NUM=[1,2,3]
      def func():
        #NUM.append(999)#可以修改父级可变类型的值
      print(NUM)#[1,2,3,999]
      
    • global :找到全局作用域中的变量

      name = "gao"
      
      
      def func():
          name = "chen"
          print(name)  # chen
      
          def func2():
              global name  # 找到全局变量name 
              name = "gao_chen"#为全局变量的name重新赋值
              print("val:" + name)  # func2内部的name gao_chen
      
          print(name)  # func 内部的chen
          func2()  #
          print(name)  # chen
      
      
      func()  # 函数执行
      print(name)  # gao_chen  内部函数通过global修改lname的值
      
      #chen
      #chen
      #val:gao_chen
      #chen
      #gao_chen
      
      
    • nonlocal :找到父级作用域中指定变量 ,【必须是父级作用域 不包括全局作用域】

    • 如果父级(父级的父级…..)作用域中不存在 则报错

      name = "gao"
      
      
      def func():
          name = "chen"
          print(name)  # chen
      
          def func2():
              nonlocal name  # 找到父级作用域的name(func中的name)
              name = "gao_chen"
              print("val:" + name)  # gao_chen
      
          print(name)  # chen
          func2()  #
          print(name)  # gao_chen
      
      
      func()  #
      print(name)  # gao
      
      
      name = "gao"
      
      def func():
          print(name)
      
          def func2():
              nonlocal name #报错  可以是父级,父级的父级 但是不能是全局
              name = "gao_chen"
              print("val:" + name)
      
          print(name)
          func2()
          print(name)
      
      func()  #
      print(name)
      
      #SyntaxError: no binding for nonlocal 'name' found
      
      name = "gao"
      
      def func():
          name = "hahahaha"
          print(name)  # hahahaha
      
          def func2():
              print("val:" + name)  # val:hahahaha
      
              def inner():
                  nonlocal name#不报错  父级的父级的name
                  name = "test"
      
              inner()
      
          print(name)  # hahahaha
          func2()
          # 其内部函数inner()也会被func2执行 因为inner()内部定义nonlocal关键字
          # 所以父级作用域的func()函数的name会被重新赋值
          print(name)  # test  被局部修改
      
      
      func()  #
      print(name)  # gao  没有被改变
      #hahahaha
      #hahahaha
      #val:hahahaha
      #test
      #gao
      
      
      
    • 全局变量尽量大写

    3.总结

    1. 函数类型

      • def func()
      • def func(a1,a2=None)
      • def func(*args,**kwargs)
    2. 函数参数

      • 形参

        • def func()
        • def func(a1,a2=None)
        • def func(*args,**kwargs)
      • 实参

        • 位置传参

        • 关键字传参

        • 传参规则: 位置参数在前,关键字参数在后

        • 默认参数

        • 万能传参

          • *args:位置传参—>可传任意类型 ——>都会转为元组

            • 调用函数时候有*
            • 调用函数时候没有*
          • **kwargs:关键字传参——>转为字典

            • 调用函数时候有*
            • 调用函数时候没有*
    3. 作用域

      • 局部和全局

      • 一个函数一个作用域

      • 作用域查找规则:

        • 自己没有父级 父级再找父级,父级都没有找全局
        • 自己->父级->父级->全局[读/修改(可变)]
        • 子作用域内不能为父级作用域内的变量重新赋值 只能读取或者修改[可变类型]
      • 重新赋值:

        • global
        • nonlocal
    4. 函数嵌套

  • 相关阅读:
    74.Interesting Sequence(有趣的数列)(拓扑排序)
    CODEVS 1746 贪吃的九头龙
    NYOJ 110 剑客决斗
    CODEVS 2451 互不侵犯
    洛谷 P1896 互不侵犯King
    洛谷 P1066 2^k进制数
    洛谷 P1656 炸铁路
    洛谷 P1830 轰炸Ⅲ
    CODEVS 1051 接龙游戏
    POJ 3461 Oulipo
  • 原文地址:https://www.cnblogs.com/koukouku/p/10685570.html
Copyright © 2011-2022 走看看