• *与**在形参与实参中的应用,函数的对象,函数的嵌套,名称空间与作用域


    一、*与**在形参与实参中的应用

    1、可变长参数
    可变长指的是参数的个数不固定
    站在实参的角度,实参是用来为形参赋值的,如果实参的个数不固定,那么必须要有对应的形参能够接收溢出实参

    2、在形参中用*与**
      2.1 在形参名前加*:*会把溢出的位置实参存成元组,然后赋值其后的形参名
    def func(x,*y):  # y=(2,3,4)
        print(x)
        print(y)
    func(1,2,3,4) #y打印出来(2,3,4)
    func(1) #y打印出来()
    func() # 报错,位置形参x必须被传值
      2.2 在形参名前加**:**会把溢出的关键字实参存成字典,然后赋值其后的形参名 
    def func(x, **y): 
        print(x)
        print(y)  # {'a': 111, 'b': 222, 'c': 333}
    func(1,a=111,b=222,c=333)
    func(a=111, b=222, x=1, c=333)

    3、在实参中用*与**

    3.1 在实参前加*:*会把其后的值打散成位置实参
    nums=[1,2,3]
    func(*nums) # func(1,2,3) #实参带*的,可以跟字典,打散取出来的是字典的key
    3.2 在实参前加**:**会把其后的值打散关键字实参 
    dic = {'y': 111, 'z': 222, 'x': 333}
    func(**dic)  # func(y=111,z=222,x=333) #实参带**的,只能跟字典,把字典打散
    
    

    4、在形参与实参中混用*与**

    ps:形参中带* **是汇总操作; 实参中带* **是打散/解压操作

    def index(x,y,z,a,b,c):  #变量名只能叫 x,y,z,a,b,c
        print("index===>",x,y,z,a,b,c)
    def wrapper(*args, **kwargs):  # args=(1, 2, 3,)   kwargs={"a":1,"b":2,"c":3}  #形参中带* **是汇总操作
        index(*args, **kwargs)  # index(*(1, 2, 3,),**{"a":1,"b":2,"c":3}) #实参中带 * ** 是打散/解压操作
                                              #  解压完后变成 index(1,2,3,c=3,b=2,a=1)
    wrapper(1, 2, 3, a=111, b=222, c=333)  #也可以a=2,b=3,c=1与位置参数传的值一样

    5、命名关键字形参(**)

    def func(x, y=222, *args, n=777,m, **kwargs):  # 夹在* ** 之间的m,n必须按照关键字实参的格式为其赋值
        print(x)  # 1
        print(y)  # 2
        print(args)  # (3,4,5)
        print("m===>", m)
        print("n===>", n)
        print(kwargs)
    
    # func(1,2,3,4,5,6666666)
    # func(1,2,3,4,5,m=6666666)
    func(1, 2, 3, 4, 5, n=88888,m=6666666, a=11, b=22, c=33)

    二、函数对象

    函数对象指的是函数可以被当成变量去使用
    1. 可以被赋值
    f = foo
    print(f is foo)
    f()
    2. 可以当作参数传给一个函数
    def bar(func):
        print(func)
        func()
    bar(foo)
    3. 可以当成一个函数的返回值
    def bar(func):
        return func
    res=bar(foo)
    print(res)
    4. 可以当成容器类型的元素
    l = [foo]
    print(l)
    l[0]()

    #利用函数对象的以上特性,优雅的取代多分支的if

    def foo():
        print('foo')
    
    def bar():
        print('bar')
    
    dic={
        'foo':foo,
        'bar':bar,
    }
    while True:
        choice=input('>>: ').strip()
        if choice in dic:
            dic[choice]()

    #案例:实现用户登录转账提现充值功能

    def login():
        print('登录功能......')
    
    
    def withdraw():
        print('提现功能......')
    
    
    def transfer():
        print('转账功能......')
    
    def recharge():
        print('充值功能')
    
    func_dic={
        "1": [login,"登录"],
        "2": [withdraw,"提现"],
        "3": [transfer,"转账"],
        "4": [recharge,"充值"]
    }
    
    # func_dic["1"][0]()
    
    
    while True:
        print("0    退出")
        for k in func_dic:
            print("%s    %s" %(k,func_dic[k][1]))
    
        choice = input("请输入你的指令编号: ").strip()
        if choice == "0":
            break
        if choice in func_dic:
            func_dic[choice][0]()
        else:
            print('输入的指令不存在')


    改进:
    choice = input('请选择功能')
    function_name = user.info(choice)
    if function_name:
    function_name()
    else:
    print('输入错误')
     


    三、函数嵌套

    1、 函数的嵌套调用
    # 案例比较:
    def max2(x,y):
        if x > y:
            return x
        else:
            return y
    max(1,2)
    # 案例比较加难度:
    def max4(a,b,c,d):
        res1 = max(a,b)
        res2 = max(res1,c)
        res3 = max(res2,d) #注意要用max比较的功能,需要直接用其本身,不要再将其赋值成max2啥的
        print(res3)
    max4(1,2,3,4)
    2、 函数的嵌套定义
    def f1():
        print('from f1')
    
        # f2 = 函数的内存地址
        def f2():
            print("from f2")
    
    f1()
    定义在函数内的函数特点是: 正常情况只能在函数体内调用
    #求圆的周长、面积(利用函数嵌套)
    from math import pi
    
    def circle(radius,mode=0):
        def perimiter(radius):
            return 2 * pi * radius
    
        def area(radius):
            return pi * (radius ** 2)
    
        if mode == 0:
            return perimiter(radius)
        elif mode == 1:
            return area(radius)
    
    res1=circle(3,0)
    res2=circle(3,1)
    print(res1)
    print(res2)
    示例:
    def func():
        x = 10
        print(x)
        def f2():
            print('from f2')
        f2()
    func()
    # print(x)#报错name 'x' is not defined

    四、名称空间与作用域

    1、 名称空间: 就是存放名字的地方
      1.1 内置名称空间: 存放的是内置的名字,如printinputlen
    生命周期: 解释器启动则产生,解释器关闭则销毁
      1.2 全局名称空间: 存放的是顶级的名字
    生命周期: python程序运行时则产生,python程序结束则销毁
      1.3 局部名称空间:函数内的名字
    生命周期: 调用函数时则产生,函数调用结束则销毁

    2、名字的查找优先级:
      从当前位置往外查找,如果当前是在局部:局部名称空间->全局名称空间->内置名称空间
      从当前位置往外查找,如果当前是在全局:全局名称空间->内置名称空间
    def func():
        len = 222
        # print(len)
    
    # len = 111
    
    func()
    
    print(len) #注意代码级别
    3、结论:
     (1)名称空间可以理解为一层套一层的关系,名称空间的嵌套关系是函数定义阶段(即扫描语法时)就固定死的,与函数的调用位置无关
    #示范1
    # x=0
    def f1():
        # x=1
        def f2():
            # x=2
            print(x)
    
        f2()
    f1()
    #示范2
    len = 111
    
    def f1():
        len=2222
    
    def f2():
        len=3333
    
    f1()
    f2()
      (2)全局范围/全局作用域:内置名称空间+全局名称空间
      特点:全局存活,全局有效
     (3)局部范围/局部作用域:局部名称空间
       特点:临时存活,局部有效
    LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
    locals 是函数内的名字空间,包括局部变量和形参
    enclosing 外部嵌套函数的名字空间(闭包中常见)
    globals 全局变量,函数定义所在模块的名字空间
    builtins 内置模块的名字空间

    4、了解
       global(****) #只能修改全局变量,在定义阶段已经弄好
      nonlocal(***) #只能修改外层变量
    #案例1
    x = 1
    def func(x): # x = 值10的内存地址
        # x = 值10的内存地址
        x = 20
    
    func(x) # func(值10的内存地址)
    print(x) # 1
    
    #案例2
    x = [11,22,33]
    
    def func(x): # x = 列表[11,22,33]的内存地址
        # x = 列表[11,22,33]的内存地址
        # x=444444444444
        x[0] = 66666
    
    func(x) # func(列表[11,22,33]的内存地址)
    print(x) #[66666, 22, 33]
    
    #案例3
    x = [11,22,33]
    def func():
        x[0] = 66666
    
    func()
    print(x) #[66666, 22, 33]
    
    #案例4
    x = 10
    def func():
        global x
        x=22
    
    func()
    print(x) # 22
    
    # 案例5:nonlocal生命名字是来自于外层函数的(***)
    x = 10
    def f1():
        x=111
    
        def f2():
            nonlocal x
            x=222
    
        f2()
        print(x) # 222
    
    f1()
    print(x) # 10
     
  • 相关阅读:
    hadoop 之 kafka 安装与 flume -> kafka 整合
    软考倒计时28天:项目一般管理
    HACMP5.4常用命令
    db2还原离线备份文件报错SQL2071N 提示“访问共享库出现错误”解决
    远程桌面不能拷贝文件的问题
    ubuntu设置开机启动命令行模式
    Rainmeter如何打开控制面板的小程序
    /var/adm/wtmp文件太大该怎么办?
    SQL1221N The Application Support Layer heap cannot be allocated. SQLSTATE=57011
    DB21019E An error occurred while accessing the directory "/root".
  • 原文地址:https://www.cnblogs.com/guojieying/p/13345478.html
Copyright © 2020-2023  润新知