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

    形参:

    1.位置传参  2. 默认值传参. 3.动态传参

    一   动态传参(形参的一种):

     之前我们说过了了传参, 如果我们需要给⼀一个函数传参, ⽽而参数⼜又是不确定的. 或者我给⼀一个
    函数传很多参数, 我的形参就要写很多, 很⿇麻烦, 怎么办呢. 我们可以考虑使⽤用动态参数.

     动态传参分两种:

    (1) 动态接收位置参数和默认值参数

    def chi(*food):# *表⽰示接收任意内容
    print("我要吃", food)
    chi("⼤大⽶米饭", "⼩小⽶米饭")
    结果:
    我要吃 ('⼤大⽶米饭', '⼩小⽶米饭') # 多个参数传递进去. 收到的内容是元组tuple

    需要注意的是 : 动态参数必须在位置参数后⾯  例如:

    def chi(*food, a, b):
    print("我要吃", food, a, b)
    chi("⼤大⽶米饭", "⼩小⽶米饭", "⻩黄⽠瓜", "茄⼦子")
    这时程序运⾏行行会报错. 因为前⾯面传递进去的所有位置参数都被*food接收了了. a和b永远接收
    不到参数

    所以必须改写成以下代码:

    def chi(*food, a, b):
    print("我要吃", food, a, b)
    chi("⼤大⽶米饭", "⼩小⽶米饭", a="⻩黄⽠瓜", b="茄⼦子") # 必须⽤用关键字参数来指

    这个时候a和b就有值了了, 但是这样写呢位置参数就不能⽤用了了. 所以. 我们要先写位置参数,

    def chi(a, b, *food):
    print("我要吃", a, b, food)
    chi("⼤大⽶米饭", "⼩小⽶米饭", "馒头", "⾯面条") # 前两个参数用位置参数来接收, 后⾯面的参数⽤动态参数
    动态参数接收

     默认值参数

    def chi(a, b, c='馒头', *food):
    print(a, b, c, food)
    chi("⾹香蕉", "菠萝") # ⾹香蕉 菠萝 馒头 (). 默认值⽣生效
    chi("⾹香蕉", "菠萝", "葫芦娃") # ⾹香蕉 菠萝 葫芦娃 () 默认值不不⽣生效
    chi("⾹香蕉", "菠萝", "葫芦娃", "口罩") # ⾹香蕉 菠萝 葫芦娃 ('口罩',) 默认值不不⽣生效

     默认值参数写在动态参数前⾯面. 默认值只有一种情况可能会⽣生效

    例子:

    def chi(a, b, *food, c="娃哈哈"): #在这里. 其实相当于把传进来的参数做了一次聚合, 聚合成一个元组
    print(a, b, food, c) 
    chi(
    "⾹香蕉", "菠萝") # ⾹香蕉 菠萝 () 娃哈哈 默认值⽣生效
    chi(
    "⾹香蕉", "菠萝", "葫芦娃") # ⾹香蕉 菠萝 ('葫芦娃',) 娃哈哈 默认值⽣生效
    chi(
    "⾹香蕉", "菠萝", "葫芦娃", "⼝口罩") # ⾹香蕉 菠萝 ('葫芦娃', '⼝口罩') 娃哈哈 默 认值生效

    这么写就生效了 这个时候如果不给出关键字传参. 那么你的默
    认值是永远都⽣生效的

    所以得到结论 :

    默认值.位置传参和动态传参的顺序为:位置  动态 默认值参数

    (2)关键字传参

    在python中使⽤用**来接收动态关键字参数

    def func(**kwargs):
    print(kwargs)
    func(a=1, b=2, c=3)
    func(a=1, b=2)
    结果:
    {'a': 1, 'b': 2, 'c': 3}
    {'a': 1, 'b': 2}         这个时候接收的是⼀一个dict

    顺序问题

    def func(a, b, c, d):
    print(a, b, c, d)
    # 关键字参数必须在位置参数后⾯面, 否则参数会混乱
    func(1, 2, c=3, 4)

    所以关键字参数必须在位置参数后⾯面. 由于实参是这个顺序. 所以形参接收的时候也是这
    个顺序. 也就是说位置参数必须在关键字参数前⾯面. 动态接收关键字参数也要在后⾯面

    综上所述最终结论顺序:

    位置参数 > *args > 默认值参数 > **kwargs        这四种参数可以任意的进行使⽤

    无敌,模式: 

    所有的参数都能接收
    def func(*args, **kwargs):
    #     print(args)
    #     print(kwargs)
    #
    # func(1, 2, 5, jj="陶喆", jay="zhoujielun", soup="胡辣汤") 
     结果为:(1, 2, 5)
    {'jj': '陶喆', 'jay': 'zhoujielun', 'soup': '胡辣汤'}

     * 和**出现在实参上时

    拿个例子来说

    def func(*args):
        print(args)
       
    lst = "娃哈哈"
    func(*lst)      结果('娃', '哈', '哈')  #  在实参位置 * 表示打散, 打散的是可迭代对象
    def func( **kwargs):
        
      print(kwargs)
      dic = {"2": "明教教主", "谢逊": "金毛狮王", "范瑶": "光明右使"}
      ##func(张无忌=dic['张无忌'], 谢逊=dic['谢逊'], 范瑶=dic['范瑶'])
      func(**dic)  结果: {'2': '明教教主', '谢逊': '金毛狮王', '范瑶': '光明右使'} 
      # 这里的** 是把字典打散. 字典的key作为参数的名字, 字典的值作为参数的值传递给形参

    小结:

           1. *args  位置参数的动态传参. 系统会自动的把所有的位置参数聚合成元组
    # 2. **kwargs 关键字的动态传参. 系统会自动把所有的关键字参数聚合成字典
    # 3. def func(*args, **kwargs): 无敌传参
    # 4. 顺序: 位置参数, *args, 默认值, **kwargs
    # 5. 在使用的时候, 可以任意的进行搭配
    # 4. 在实参上. *, **表示的打散. 在形参. *,** 表示聚合

    二    命名空间

    1.名称空间

      内置空间    ::存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置空间

      全局空间:   :我们直接在py⽂文件中, 函数外声明的变量量都属于全局命名空间

      局部空间 :  ;在函数中声明的变量量会放在局部命名空间

    加载顺序:

    1. 内置命名空间

    2. 全局命名空间
    3. 局部命名空间(函数被执⾏行行的时候)

    最开始会开辟一个自己的命名空间- 内置名称空间

    a = 10 # 全局 # def func(): # # a = 20# 局部 # print(a)#局部 # # func()

    取值顺序:

      局部 => 全局 => 内置

      作用域(变量或者函数的声明周期)

    作⽤用域就是作⽤用范围, 按照⽣生效范围来看分为 全局作⽤用域和局部作⽤用域
    全局作⽤用域: 包含内置命名空间和全局命名空间. 在整个⽂文件的任何位置都可以使⽤用(遵循
    从上到下逐⾏行行执⾏行行). 局部作⽤用域: 在函数内部可以使⽤用.

    全局作用域: 全局名称空间+内置名称空
    局部作用域: 局部名称空间
    1.我们可以通过globals()函数来查看全局作⽤用域中的内容, 也可以通过locals()来查看局部作
    ⽤用域中的变量量和函数信息
    1. globals() 查看全局作用域中的所有内容
    # qiao = "乔峰"
    # def 抗收音机():
    # bgm = "难念的经"
    # print("娃哈哈")
    # print(locals())
    # 抗收音机() #


      print(globals())  ## 查看全局作用域中的内容

    print(locals()) # locals()查看的是当前作用域中的内容

    四 函数的嵌套

    1. 只要遇⻅见了了()就是函数的调用. 如果没有()就不是函数的调⽤

    def func1():
    #     print("我是func1")
    #
    # def func2():
    #     print("我是func2")
    #     func1()
    #
    # def func3():
    #     func2()
    #     print("我是func3")
    # func3()
    # 这样的代码不是嵌套. 互相调用

    2. 函数的执行顺序

    简单的嵌套  例子1

    ef outer():
    #     def inner():
    #         print("我是内部")
    #     print("我是外部")
    #     inner()
    #
    # outer()

    例子2

    ef outer():
    #     print("我是外面的")
    #     def inner_1():
    #         def inner_2():
    #             print("我是里面的2")
    #         inner_2()
    #         print("我是里面的1")
    #     inner_1()
    #     print("我是外面的收尾")
    #
    # outer()

    3.关键字global和nonlocal

    首先在全局声明一个变量, 然后再局部调用这个变量, 并改变这
    个变量的值

    global表示. 不再使用局部作用域中的内容了. 而改用全局作用域中的变量

    a = 100
    def func():
      global a # 加了了个global表示不再局部创建这个变量了. 而是直接使用全局的a 把全局的变成和局部一样的变量
      a = 28
      print(a)
    func()
    print(a)      

     a = 10
    # def func():
    #     global a #表示在当前作用域中的使用的a是全局中的变量
    #     a = 20 # 所有的a都是外面的了
    #     print(a) # 现在只有看的权利
    #

    例子2

    lst = ["麻花藤", "刘嘉玲", "詹姆斯"]
    def func(): lst.append(
    "⻢马云云") # 对于可变数据类型可以直接进⾏行行访问. 但是不不能改地址. 说⽩白 了了. 不不能赋值 print(lst) func() print(lst)

    nonlocal(找的是局部当中, 离他最近的上层的那个变量)

    def outer():
    #     a = 10
    #     def inner():
    #         nonlocal a # 找的是局部当中, 离他最近的上层的那个变量
    #         a = 20
    #         print(a)
    #     print(a) # 10
    #     inner() # 20
    #     print(a) # 20
    # outer()
     global 引入全局变量, 可以定义全局变量
    nonlocal 引入局部中离他最近的外层变量
    def func():
        global a # 没有也得有. 自动帮你创建    # 定义全局变量  
        a = 20
    
    func()
    print(a)  
  • 相关阅读:
    Java泛型 PECS(Producer Extends, Consumer Super)
    JDK(七)JDK1.8源码分析【集合】TreeMap
    JDK(六)JDK1.8源码分析【集合】LinkedHashMap
    JDK(五)JDK1.8源码分析【集合】HashMap
    JDK(四)JDK1.8源码分析【排序】DualPivotQuicksort
    JDK(三)JDK1.8源码分析【排序】mergeSort
    JDK(二)JDK1.8源码分析【排序】timsort
    第24天多线程技术
    第23天功能流、图形化界面、多线程
    第二十二天 字符流、缓冲区、转换流
  • 原文地址:https://www.cnblogs.com/systemsystem/p/9647770.html
Copyright © 2011-2022 走看看