• 可变长参数,函数的对象,函数嵌套,名称空间和作用域


    1.可变长参数

    可变长参数:在调用函数时,参入的参数个数可以不固定。

    调用函数时,传值的方式莫非两种,一种是位置实参,另一种是关键字实参,因此形参也必须的有两种解决方式,以此来分别接收溢出的位置实参(*)也关键字实参(**)

    一.可变长形参之*

    形参中的会将溢出的位置实参全部接收,然后存储元组的形式,然后把元组赋值给后的参数。需要注意的是:*后的参数名约定俗成为args。

    def sum(*args):
        res = 0
        for sum_new in args:
            res += sum_new
        return res
    res = sum(1,2,3,4,5)
    print(res)   # 15
    
    

    二 .可变长实参之*

    实参中的会将后参数的值循环取出,达三成位置实参。以后但凡碰到实参中带的,他就是位置实参,应该马上打散成位置实参去看。

    def func(a,b,*,c,d):
    	print(a,b)
    	print(c,d)
    
    lst = [10,11]
    ''' *lst 相当于把列表中的每一个元素单独拿出来,扔到参数中进行赋值;'''
    func(*lst,c=12,d=13) # func(10,11,c=12,d=13)
    
    列二:
    def func(x, y, z, *args):
        print(x, y, z, args)
    func(1, *(1, 2), 3, 4)#1,1,2,(3,4)
    

    三. 可变长实参之**

    形参中的** 会将溢出的关键字实参全部接收,然后存储字典的形式,然后把字典赋值给** 后的参数。需要注意的是:**后的参数名约定俗成为kwargs。

    def func(**kwargs):
        print(kwargs)
    func(a=5)  #{"a":5}
    

    四 .可变长实参之**

    实参中的会将** 后参数的值循环取出,打散成关键字实参。以后但凡碰到实参中带**的,它就是关键字实参,应该马上打散成关键字实参去看。

    def func(x,y,z,**kwargs):
        print(x,y,z,kwargs)
    func(1,2,3,**{"a":1,"b":2})
    #1 2 3 {'a': 1, 'b': 2}
    
    列er:深
    def func(a,b,*,c,d):
    	print(a,b)
    	print(c,d)
    dic = {"c":12,"d":13}
    ''' **dic 相当于把字典当中每一个元素变成 c=12,d=13 的形式传入关键字实参 '''
    func(10,11,**dic) #func(10,11,c=12,d=13)
    

    五 .可变长参数的列题应用。

    ndex(name ,age,hobby):
        print(f"name:{name},age:{age},hobby:{hobby}")
    def guess(*args,**kwargs):
        print(f'args:{args}')
        print(f'kwargs:{kwargs}')
        index(*args,**kwargs)
    guess(name="liangjing",age="20",hobby="购物,run,听音乐")
    #args:()
    #kwargs:{'name': 'liangjing', 'age': '20', 'hobby': '购物,run,听音乐'}
    #name:liangjing,age:20,hobby:购物,run,听音乐
    

    六. 关键字形参

    现在有一个需求,函数的使用者必须按照关键字实参传。

    def register(x, y, **kwargs):
        if 'name' not in kwargs or 'age' not in kwargs:
            print('用户名和年龄必须使用关键字的形式传值')
            return
        print(kwargs['name'])
        print(kwargs['age'])
    register(1, 2, name='liangjing', age=20)
    #liangjing
    # 20
    

    命名关键字形参:在函数定义阶段,*后面的参数都是命名关键字参数。

    特点:在传值时,必须按照key=value的方式传值,并且key必须命名关键字参数的指定的参数名。

    2.函数的对象

    函数是第一类对象,即函数可以被当做数据处理。

    一 . 函数对象的四大功能。

    1.引用

    def f1():
        print('from f1')
    
    # 函数对象 == 函数名  # 函数名()就是在调用,没有其他的意思
    
    # 1. 引用
    func = f1
    print('f1:', f1)  #f1: <function f1 at 0x0000019E710BA1F8>  f1打印地址
    print('func:', func) #func: <function f1 at 0x0000019E710BA1F8>
    
    func()#  from f1
    

    2.当作容器类元素

    def f1():
        print('from f1')
    
    # 函数对象 == 函数名  # 函数名()就是在调用,没有其他的意思
    
    # 1. 引用
    lt = [f1, 1, 2, 3]
    print('lt[0]', lt[0]) #lt[0] <function f1 at 0x000002628657A1F8>
    print('f1', f1)#f1 <function f1 at 0x000002628657A1F8>
    lt[0]()#form f1
    
    1. 当作函数参数
    def f1():
        print('from f1')
    def f2(f2_f1):
    	print('f2_f1',f2_f1)
    	f2_f1()
    	f2(f1)
    print('f1', f1)
    #f2_f1 <function f1 at 0x000001A00C79A318>
    #from f1
    # f1 <function f1 at 0x000001A00C79A318>
    
    
    1. 当作函数的返回值
    def f1():
        print('from f1')
    def f2(f2_f1):
        return f2_f1
    res = f2(f1)
    print('res', res)  #res <function f1 at 0x000001D6E002A168>
    print('f1', f1)  #f1 <function f1 at 0x000001D6E002A168>
    res() #from f1
    
    

    3.函数对象的练习。

    def register():
        print('register')
    
    def login():
        print('login')
    
    def withdraw():
        print('wightdraw')
    
    def shopping():
        print('shopping')
    
    func_dict = {
        '1': register,
        '2': login,
        '3': withdraw,
        '4': shopping,
    }
    
    print('''
    1 注册
    2 登录
    3 提现
    4 购物
    ''')
    
    while True:
        choice = input('请选择你需要的功能(输入q退出):')
        if choice == 'q':
            break
        func_dict[choice]()
    
    

    4.函数嵌套。

    一 . 函数的嵌套定义

    #定义函数,只检测语法,不会执行代码
    def f1():
        def f2():
            print('from f2')
        f2()
    
    f2()  # NameError: name 'f2' is not defined(报错:没有定义f2)
    
    

    定义后

    def f1():
        def f2():
            print('from f2')
        f2()
    
    f1() #from f2
    
    

    现在有个需求,通过函数做一个九九乘法表。

    #方法
    # # 打印九九乘法表
    # for i in range(1, 10):  # i控制的是行
    #     for j in range(i):  # j控制的是列
    #         print(f'{j+1}*{i}={(i)*(j+1)}', end=' ')
    #
    #     print()  # 打印换行
    #
    # '''
    # i控制行,j控制列
    # i = 1  for j in range(1) j = 0 + 1
    # i = 2  for j in range(2) j = 0 + 1 j = 1 + 1
    # i = 3  for j in range(3) j = 0 + 1 j = 1 +1 j = 2 + 1
    # i = 4
    # i = 5
    ##################################################################
    # 函数的定义 
    #def 函数名(等同于变量名)():
    #     """对函数(工具)的描述信息"""
    #     代码块
    def chengfabiao():
        """描述的信息"""
        for i in range(1, 10):
            for j in range(1, i + 1):
                print("%d*%d=%2d " % (i, j, i * j), end="")
            print()
            
    # 函数的调用
    chengfabiao()
    chengfabiao()
    chengfabiao()
    #结果:
    1*1= 1 
    2*1= 2 2*2= 4 
    3*1= 3 3*2= 6 3*3= 9 
    4*1= 4 4*2= 8 4*3=12 4*4=16 
    5*1= 5 5*2=10 5*3=15 5*4=20 5*5=25 
    6*1= 6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 
    7*1= 7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 
    8*1= 8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 
    9*1= 9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
    
    
    

    二 .函数的嵌套调用。

    def max2(x, y):
        if x > y:
            return x  #return是一个返回值,默认返回较大的数。
        else:
            return y
    
    def max4(a, b, c, d):
        res1 = max2(a, b) 
    #调用值max4拿到res1中,这时a=1,b=2带max2中进行比较x=1,y=2,此时y大,res1=2(b),将b(b=2)带入res2进行比较,依次比较下去。                 
        res2 = max2(res1, c)
        res3 = max2(res2, d)
        return res3
    
    print(max4(1, 2, 3, 4)) #4   
    
    

    列:

    # 定义函数,只检测语法,不会执行代码
    def f1():
        print('from f1')
    
        def f2():
            print('from f2')
    
    res = f1()#打印的是外部的值 from f1
    
               # ***:函数内部定义的函数,外部不能用
    
    

    5.名称空间和作用域

    变量名/函数名 --》 名称 --》=专门存储名称的

    名称空间(name spaces):在内存管理那一章节时,我们曾说到变量的创建其实就是在内存中开辟了一个新的空间。但是我们一直在回避变量名的存储,其实在内存中有一块内存存储变量名与变量间的绑定关系的空间,而这个空间称为名称空间。(存储了内置方法的名称)

    一. 内置名称空间

    内置名称空间:存放Pyhton解释器自带的名字,如int、float、len

    生命周期:在解释器启动时生效,在解释器关闭时失效

    二.全局名称空间(执行文件代码的时候才会有全局)

    全局名称空间:除了内置和局部的名字之外,其余都存放在全局名称空间,如下面代码中的x、func、l、z

    生命周期:在文件执行时生效,在文件执行结束后失效

    x = 1
    
    def func():
        pass
    
    l = [1, 2]
    
    if 3 > 2:
        if 4 > 3:
            z = 3
    
    

    三 . 局部名称空间 (函数调用的时候才会有局部)

    局部名称空间:用于存放函数调用期间函数体产生的名字,如下面代码的f2

    生命周期:在文件执行时函数调用期间时生效,在函数执行结束后失效。

    def f1():
        def f2():
            print('from f2')
        f2()
    
    f1() 
    
    

    四. 加载顺序

    由于.py文件是由Python解释器打开的,因此一定是在Python解释器中的内置名称空间加载结束后,文件才开始打开,这个时候才会产生全局名称空间,但文件内有某一个函数被调用的时候,才会开始产生局部名称空间,因此名称空间的加载顺序为:内置--》全局--》局部。

    五 .搜索顺序:先从当前所在位置寻找,找不到再按照这种顺序,不会逆着方向寻找 局部 --》 全局 --》 内置 --》 报错

    二 . 作用域

    一.作用域:域指的是区域,作用域即作用的区域。

    二 .全局作用域

    全局作用域:全局有效,全局存活,包含内置名称空间和全局名称空间。

    # 全局作用域
    x = 1
    
    def bar():
        print(x)
    
    bar()  #1
    
    

    三 .局部作用域

    局部作用域:局部有小,临时存储,只包含局部名称空间。

    # 局部作用域
    def f1():
        def f2():
            def f3():
                print(x)
            x = 2
            f3()
        f2()
    
    f1() #2
    
    

    四. 注意点需要注意的是:作用域关系在函数定义阶段就固定死了,与函数的调用无关。

    x = 1
    
    def f1():  # 定义阶段x=1
        print(x)
    
    def f2():
        x = 2
        f1()
    
    f2()#1   与函数的调用无关
    
    

    五. 函数对象+作用域应用

    # 作用域应用
    def f1():
        def inner():
            print('from inner')
        return inner
    
    f = f1()  # 把局部定义的函数放在全局之中
    
    def bar():
        f()
    
    bar()  #from inner
    
    

    六 . global关键

    修改全局作用域中的变量。

    七. nonlocal 关键字

    修改局部作用域中的变量。

    八 .注意点

    3.3 注意点

    1. 在局部想要修改全局的可变类型,不需要任何声明,可以直接修改。
    2. 在局部如果想要修改全局的不可变类型,需要借助global声明,声明为全局的变量,即可直接修改。
    lis = []
    
    def f1():
        lis.append(1)
    
    print(f"调用函数前: {lis}")
    f1()
    print(f"调用函数后: {lis}")
    #调用函数前: []
    #调用函数后: [1]
    
    
  • 相关阅读:
    关于静态链接库(Lib,.A)与动态链接库(DLL,.SO)
    #pragma once
    动态链接库和静态链接库的区别
    C++编写、生成、调用动态链接库
    cmake 命令行
    Build Slicer application--Compiling and installing Slicer from source
    3DSlicer开发之路——Extensions(九)
    3DSlicer开发之路——Extensions(八)
    3DSlicer开发之路——Extensions(七)
    placeholder文字颜色与是否显示兼容性
  • 原文地址:https://www.cnblogs.com/WQ577098649/p/11559820.html
Copyright © 2020-2023  润新知