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

    函数的进阶

    函数参数--动态传参

    之前我们说过了传参, 如果我们需要给一个函数传参, 而参数又是不确定的. 或者我给一个
    函数传很多参数, 我的形参就要写很多, 很麻烦, 怎么办呢. 我们可以考使用动态参数.
    形参的第三种: 动态参数
    动态参数分成两种 :

    1.动态接受位置参数

    首先我们要回顾一下位置参数,位置参数,按照位置进行传参

    现在问题来了. 我想吃任意的食物. 数量是任意的, 食物也是任意的. 这时我们就要就到
    动态参数了.
    在参数位置编写*表示接收任意内容

    def chi(*food): # * 表示的是不定参数. 可以传递任意个信息 参数名是food, 接受到的是元组
        print("我要吃", food)
    
    chi("一锅大米饭", "一箱辣条", "一桶方便面", "4L可乐")
    chi("方便面")
    chi("一大锅米饭", "一小锅小米饭", "一箱辣条", "一桶方便面", "4L可乐")

     动态接收参数的时候要注意: 动态参数必须在位置参数后:

    这时程序运行会报错. 因为前⾯传递进去的所有位置参数都被*food接收了. ab接收
    不到参数

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

    这个时候ab就有值了, 但是这样写呢位置参数就不能用了. 所以. 我们要先写位置参数,
    然后再用动态参数

     

    如果默认值参数在*args前面. 如果想让默认值生效. *args将永远接不到值
    def func( a, b, *args,c = 5): # arguments参数
        print(a, b, c, args)
    
    func(1,2,3,4,5,6,8,c = 10)

    这个时候我们发现所有的默认值都生效了. 这个时候如果不给出关键字传参. 那么你的默
    认值是永都生效的

     顺序: 位置参数, 动态参数*, 默认值参数

     2. 动态接收关键字参数
    python中可以动态的位置参数, 但是*这种情况只能接收位置参数用法接收关键字参数.
    python中使用**来接收动态关键字参数

    def func(**kwargs): # key word arguments
        print(kwargs)
    
    func(a=10, b=20, jay="周杰伦", jj="林俊杰")

    这个时候接收的是一个dict
    顺序的问题, 在函数调用的时候, 如果先给出关键字参数, 则整个参数列表会报错.

     

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

    最终顺序:位置参数 > *args >默认值参数 >**kwargs

    这四个参数可以接受任意使用

    如果要接受所有的参数:

    # 无敌模式. 所有的参数都能接收
    def func(*args, **kwargs):
        print(args)
        print(kwargs)
    func(1, 2, 5, jj="陶喆", jay="zhoujielun", soup="胡辣汤")

    def func(*args): # 在这里. 其实相当于把传进来的参数做了一次聚合, 聚合成一个元组
        print(args)
    
    lst = "娃哈哈"
    func(*lst) #  在实参位置 * 表示打散, 打散的是可迭代对象
    def func(**kwargs): # ** 把接收到的关键字参数打包(聚合)成字典
        print(kwargs) # 一定是字典
    
    dic = {"张无忌": "明教教主", "谢逊": "金毛狮王", "范瑶": "光明右使"}
    
    func(张无忌=dic['张无忌'], 谢逊=dic['谢逊'], 范瑶=dic['范瑶'])
    func(**dic) # 这里的** 是把字典打散. 字典的key作为参数的名字, 字典的值作为参数的值传递给形参
    在形参上
    1. 位置参数
    2. 默认值参数
    3. 动态参数
    1. *args 位置参数的动态传参. 系统会自动的把所有的位置参数聚合成元组
    2. **kwargs 关键字的动态传参. 系统会自动把所有的关键字参数聚合成字典
    3. def func(*args, **kwargs): 无敌传参
    4. 顺序: 位置参数, *args, 默认值, **kwargs
    5. 在使用的时候, 可以任意的进行搭配
    4. 在实参上. *, **表示的打散. 在形参. *,** 表示聚合

    命名空间:

    python解释器开始执⾏之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候,
    把变量名和值之间的关系记录下来, 但是当遇到函数定义的时候, 解释器只是把函数名读入内
    , 表示这个函数存在了, 至于函数内部的变量和逻辑, 解释器是不关心的. 也就是说一开始
    的时候函数只是加载进来, 仅此而已, 只有当函数被调用和访问的时候, 解释器才会根据函数
    内部声明的变量来进行开辟变量的内部空间. 随着函数执⾏完毕, 这些函数内部变量占用的空
    间也会随着函数执行完毕而被清空.

    # 最开始会开辟一个自己的命名空间- 内置名称空间
    a = 10
    print(a)
    # 直接在py文件一个层面上是全局名称空间
    def func():
        hasakey = 10
    # 在函数内部属于局部名称空间
    func()
    加载顺序: 内置 => 全局 => 局部
    取值顺序: 局部 => 全局 => 内置
    a = 10 # 全局
    def func():
        a = 20
        print(a)
    
    func()

    作用域: 作用域就是作用范围, 按照生效范围来看分为 全局作用域和局部作用域
    全局作用域: 包含内置命名空间和全局命名空间. 在整个文件的任何位置都可以使用(遵循
    从上到下逐行执行). 局部作用域: 在函数内部可以使用.
    作用域命名空间:
    1. 全局作用域: 全局命名空间 + 内置命名空间
    2. 局部作用域: 局部命名空间
    我们可以通过globals()函数来查看全局作⽤域中的内容, 也可以通过locals()来查看局部作用
    域中的变量和函数信息

    作用域: 变量或者函数的声明周期
    全局作用域: 全局名称空间+内置名称空间
    局部作用域: 局部名称空间
    a = 10 # 全局
    def func():
        liuwei = "刘伟"
    # 1. globals() 查看全局作用域中的所有内容
    qiao = "乔峰"
    def 抗收音机():
        bgm = "难念的经"
        print("娃哈哈")
        print(locals())
    抗收音机()
    
    # print(globals()) # 查看全局作用域中的内容
    # print(locals()) # locals()查看的是当前作用域中的内容

     

    函数的嵌套

    1. 只要遇见了()就是函数的调用. 如果没有()就不是函数的调用
    2. 函数的执行顺序

    def func1():
        print("我是func1")
    
    def func2():
        print("我是func2")
        func1()
    
    def func3():
        func2()
        print("我是func3")
    func3()
    这样的代码不是嵌套. 互相调用
    函数可以互相嵌套
    def outer():
        def inner():
            print("我是内部")
        print("我是外部")
        inner()
    
    outer()
    
    def outer():
        print("我是外面的")
        def inner_1():
            def inner_2():
                print("我是里面的2")
            inner_2()
            print("我是里面的1")
        inner_1()
        print("我是外面的收尾")
    
    outer()

     

    关键字 global和nonlocal

      首先我们要写这样的一个代码,首先在全局声明一个变量然后再局部调用这个变量,改变这个变量的值

    a = 10
    def func():
        global a #表示在当前作用域中的使用的a是全局中的变量
        a = 20 # 所有的a都是外面的了
        print(a) # 现在只有看的权利
    
    print(a) # 10
    func() # 20
    print(a) # 20
    def outer():
        a = 10
        def inner():
            nonlocal a # 找的是局部当中, 离他最近的上层的那个变量
            a = 20
            print(a)
        print(a) # 10
        inner() # 20
        print(a) # 20
    outer()

    深坑:

    a = 1
    def fun_1():
        a = 2
        def fun_2():
            nonlocal a
            a = 3
            def fun_3():
                a = 4
                print(a)
            print(a)
            fun_3()
            print(a)
        print(a)
        fun_2()
        print(a)
    print(a)
    fun_1()
    print(a)
    nonlocal深坑

    # global 引入全局变量, 可以定义全局变量
    # nonlocal 引入局部中离他最近的外层变量

    def func():
        global a # 没有也得有. 自动帮你创建
        a = 20
    
    func()
    print(a)

    练习:

    # 写函数,接收n个数字,求这些参数数字的和。(动态传参)
    def func(*n):
        sum = 0
        for el in n:
            sum += el
        return sum
    
    ret = func(1,2,5,4,7)
    
    
    # 写函数,传入函数中多个实参(均为可迭代对象如字符串,列表,元祖,集合等),
    # 将每个实参的每个元素依次添加到函数的动态参数args里面.
    # 例如 传入函数两个参数[1,2,3] (22,33)最终args为(1,2,3,22,33)
    
    def func(*args): # str, list, tuple, set
        print(args)
        lst = []
        for el in args:
            for e in el:
                lst.append(e)
        tu = tuple(lst)
        print(tu)
    #
    func(*"哈哈", *[1,3,5], *(456,789))
    
    
    # 写函数,传入函数中多个实参(实参均为字典),将每个实参的键值对依次添加到函数的动态参数kwargs里面.
    # 例如 传入函数两个参数{‘name’:’alex’} {‘age’:1000}最终kwargs为{‘name’:’alex’ ,‘age’:1000}
    def func(**kwargs):
        print(kwargs)
    
    func(**{"alex": "大帅逼", "wusir":""})
    
    
    
    # 9,写函数,接收一个参数(此参数类型必须是可迭代对象),将可迭代对象的每个元素以’_’相连接,形成新的字符串,并返回.
    # 例如 传入的可迭代对象为[1,'老男孩','武sir']返回的结果为’1_老男孩_武sir’
    def func(it):
        result = ""
        for el in it:
            result += str(el) + "_"
        return result[:-1]
        
        for i in range(len(it)):
            el = str(it[i])
            it[i] = el
        return "_".join(it)
    
    print(func([1,"alex","wusiar"]))
    print("alex"+213)
    
    
    # 写函数,传入n个数,返回字典{‘max’:最大值,’min’:最小值}
    # 例如:min_max(2,5,7,8,4) 返回:{‘max’:8,’min’:2}(此题用到max(),min()内置函数)
    
    def func(*n):
        return {"最大值":max(n), "最小值":min(n)}
    
    print(func(1,8,6,4,5,15,63,35,5))
    
    
    # 求阶乘
    def func(n):
        sum = 1
        for i in range(n, 0, -1):
            sum *= i
        return sum
    print(func(5))
    
    
    
    # 写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组
    # 例如:[(‘红心’,2),(‘草花’,2), …(‘黑桃’,‘A’)]
    
    # 花色:红黑芳草
    # 点数: A2345678910
    # 笛卡儿积.
    def func():
        hua = ["红心", "黑桃", "梅花", "方块"]
        dian = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
        result = []
        for huase in hua:
            for dianshu in dian:
                result.append((huase, dianshu))
        return result
    #
    #
    def wrapper():
        def inner():
            print(666)
    
        return inner # 函数名可以作为变量返回
    #
    #
    fn = wrapper()
    fn()
    
    def extendList(val, list=[]): # 默认值在内存中只会产生一份
        list.append(val)
        return list
    
    list1 = extendList(10)
    print('list1=%s' % list1)
    list2 = extendList(123, [])
    print('list2=%s' % list2)
    list3 = extendList('a')
    print('list3=%s' % list3)
    
    print(id(list1))
    print(id(list3))
    print(id(list2))
    练习
    
    
  • 相关阅读:
    Mysql命令下导出select查询数据之 select ... into outfile方法
    接口调试工具Postman之自动同步Chrome cookies,实现自动登陆验证
    PHP函数file_get_contents()使用 https 协议时报错:SSL operation failed
    MySQL中连接超时自动断开的解决方案
    UEditor富文本WEB编辑器设置代码高亮
    Laravel 自定义公共函数全局使用,并设置自定加载
    Laravel 解决blade模板转义html标签问题
    PHP 高效导入导出Excel(csv)方法之fgetcsv()和fputcsv()函数
    Mysql命令行tab自动补全方法
    PHP利用get_headers()函数判断远程的url地址是否有效
  • 原文地址:https://www.cnblogs.com/zhaodingding/p/9669744.html
Copyright © 2011-2022 走看看