zoukankan      html  css  js  c++  java
  • 函数/匿名函数

    函数的定义

    def func():
        print(1)
        print(2)
        print(3)
        return
        print(4)
    func()
    
    结果:
    1
    2
    3
    4
    View Code

    定义:def 关键字开头,空格之后接函数名和圆括号(),最后为冒号:,def 是固定的不能改变,空格将def关键字和函数名分开,函数名的命名规则和变量一样

    调用:就是 函数名()

    rerutn : 当函数遇到return是,函数结束执行

    函数的执行流程

    函数只有在调用时才会执行,由上到下逐行执行

    函数的返回值

    return 关键字 ,谁调用就返回给谁

    def func():
        s = 1+2
        print(s)
    sum1 = func()
    print(sum1)
    View Code

     不写retnrn时,会默认返回一个None

    def func():
        s = 1+2
        print(s)
    sum1 = func()
    print(sum1)
    
    结果:
    3
    None
    View Code

    只写return,后面不写其他内容,也会返回None

    def func():
        s = 1+2
        print(s)
        return
    sum1 = func()
    print(sum1)
    
    结果:
    3
    None 
    View Code

    写return和不写return的区别,当函数中遇到return时,此函数结束,不会在继续执行

    def func():
        s = 1+2
        return
        print(s)   #print(s)并没有执行
    sum1 = func()
    print(sum1)
    
    结果:
    None
    View Code

    返回一个值,返回的是值,而不是某个变量,返回的数据类型是其本身的数据类型

    def func():
        s = 1+2
        return s,1,2,['a','b']
    sum1 = func()
    print(sum1)
     结果: 3
    View Code

    返回多个值

    def func():
        s = 1+2
        return s,1,2,['a','b']
    sum1 = func()
    print(sum1)
    
    结果:
    (3, 1, 2, ['a', 'b'])  
    View Code

    返回的多个值会被组织成一个元组被返回,也可以用多个值来接受

    def func():
        return 1,2,['q','w'],3
    a,b,c,d = func()
    print(a,b,c,d)
    结果:
    1 2 ['q', 'w'] 3
    View Code

    注意:return和返回值之间要有空格,可以返回任意数据类型的值

     函数的参数

     参数:也就是函数括号里的内容  函数在调用的时候指定一个具体的变量的值 就是参数

    def func(n):    #形参
        print("hello"+n)
    func("world")  #实参    #将wolrd传入到n的过程叫传参
    View Code

    传入多个参数,参数之间用逗号分隔

    def func(x,y):
        max1 = x if x > y else y
        return max1
    n = func(3,4)
    print(n)
    View Code

    位置参数

    按照位置传值,实参的角度

    def func(x,y):
        # 此时 x=3 y=4
        max1 = x if x > y else y
        return max1
    n = func(3,4)
    print(n)
    View Code

    按照关键字传值

    def func(x,y):
        # 此时 x=4 y=3
        max1 = x if x > y else y
        return max1
    n = func(y=3,x=4)
    print(n)
    View Code

    混合传参

    def func(x,y):
        # 此时 x=4 y=3
        max1 = x if x > y else y
        return max1
    n = func(4,y=3)
    print(n)
    View Code

    注意:位置参数必须在关键字参数前面,对于一个形参只能赋值一次

    默认参数

    将变化比较小的值设置为默认参数

    默认参数

    def func(name,state = "CN"):
        print(name,state)
    func('wanglan')
    View Code

    想要修改默认参数,传值即可

    def func(name,state = "CN"):
        print(name,state)
    func('wanglan','USA')
    View Code

    默认参数陷阱

    def func(a,l=[]): # 当函数执行时,发现有默认参数,会在内存中生成一个列表,l=[]只会创建一次,并不会多次创建,在函数内部使用时相当于全局变量,只是其它函数无法使用
        l.append(a)
        print(l)
    func(1) #当函数调用时,会在列表中添加1
    func(2) #第二次调用,会继续添加
    func(3) #第三次调用,继续添加
    
    结果:
    [1]
    [1, 2]
    [1, 2, 3]
    View Code
    def func(a,l=[]): #只要是默认参数是一个可变数据类型,通过默认参数对其修改,修改的就是同一个
        l.append(a)
        print(l)
    func(1) #使用默认参数修改
    func(2,[]) #不在使用默认参数,传入一个空列表
    func(3)  #使用默认参数修改
    
    结果:
    [1]
    [2]
    [1, 3]
    View Code

    动态位置参数

     按位置传值多余的参数由args统一接受,保存成一个元组的形式

    def func(*args):
        print(args)
    func('Hello','world','wang','lan')
    
    结果:
    ('Hello', 'world', 'wang', 'lan')  #收到的结果是一个元组
    View Code

    注意:动态参数要写在位置参数后面

     动态默认参数

     按默认传值多余的参数由kwargs统一接受,保存成一个字典的形式

    def func(**kwargs):
        print(kwargs)
    func(a = 'Hello',b = 'world',c = 'wang',d = 'lan')
    
    结果:
    {'a': 'Hello', 'b': 'world', 'c': 'wang', 'd': 'lan'}  #收到的结果是一个字典
    View Code

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

     其他传参方式

     接受所有的参数

    def func(*args,**kwargs):
        print(args,kwargs)
     func(1,23,5,a=1,b=6)
    View Code

    动态参数其他传参

    st = [1,4,7]
    # 方法一
    def func(*args):
        print(args)
     func(lst[0],lst[1],lst[2])
     
    # 方法二
    def func(*args):# 在形参的位置上用*把收到的参数组合成一个元祖
        print(args) 
    func(*lst)  #在实参的位置上用*将lst(可迭代对象)按照顺序打散
    View Code

    字典也可以进行打散,不过需要**

    def func(**kwargs):
        print(kwargs)  #返回字典
    func(**dic)
    
    
    def func(**kwargs):
        print(*kwargs) #加上*返回的就是字典的key
    func(**dic)
    View Code

    命名空间和作用域

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

    def fun():   
        a = 10
        print(a)
    fun()
    print(a)    # a不不存在了了已经
    
    结果:
    NameError: name 'a' is not defined
    View Code

    命名空间:
        内置命名空间 :作用域 全局和局部,加载是在运行之后,代码之前
        全局命名空间 :作用域 全局和局部,加载是在运行代码的时候
        局部命名空间 :作用域 在局部,加载是在调用的时候

    加载顺序:

        内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载

    取值 :

        在局部调用:局部命名空间->全局命名空间->内置命名空间 

    x = 1
    def func():
        x = 2      #局部存在使用局部
        print(x)
    func()
    
    结果
    2
    
    x = 1
    def func():
        x = 2
        def func1():  #不存在调用父级,找到就使用,找不到就使用全局
            print(x)   
        func1()
    func()
    
    结果
    2
    View Code

    覆盖 :
        同一个名字 : 局部覆盖全局和内置,全局覆盖内置
        永远不要起和你知道的内置命名空间中重名的名字 

    可以通过globals()函数来查看全局作用域中的内容,  也可以通过locals()来查看局部作用域中的变量量和函数信息

    def func():
        a = 40
        b = 20
        print("哈哈")
        print(a, b)     # 这里使用的是局部作用域
        print(globals())    # 打印全局作用域中的内容
        print(locals())     # 打印局部作用域中的内容
    func()
    View Code

    函数的嵌套

    def f1():
        def f2():
            def f3():
                print("in f3")
            print("in f2")
            f3()
        print("in f1")
        f2()
    f1()
    View Code
    def max2(x,y):
        m  = x if x>y else y
        return m
    def max4(a,b):
        res1 = max2(a,b) #调用max2函数
        return res1
    n = max4(6,2)
    print(n)
    View Code

    global和nonlocal

    global:在局部改全局

    a = 10
    def func():   
        global a    # 加了个global表示将局部变量改为全局变量
        a = 20   
    print(a)
    func()
    print(a)
    View Code

    nonlocal:在小局部改大局部,两个局部之间一定有嵌套关系(修改父级变量),如果父级没有继续向上找,直到函数的第一层,如果还没有就保错,nonlocal不能修改全局变量

    def f1():
        a = 1
        def f2():
            nonlocal a  #更改父级变量
            a = 2   #将父级变量的a=1 修改为a =2 
        f2()
        print('a in f1 : ',a)
    
    f1()
    View Code

    函数名的本质

    1. 函数名可以被引用

    def func():
        print('in func')
    f = func
    print(f)
    View Code

    2函数名可以被当作容器类型的元素

    def f1():
        print('f1')
    
    
    def f2():
        print('f2')
    
    
    def f3():
        print('f3')
    
    l = [f1,f2,f3]
    d = {'f1':f1,'f2':f2,'f3':f3}
    
    #调用
    l[0]()
    d['f2']()
    View Code

    3.函数名可以当作函数的参数和返回值,就是可以当普通变量用

    def login_failed():
        print('登陆失败')
    
    def index():
        print('欢迎来到首页')
    
    def login(usr,pwd):
        if usr == 'wanglan' and pwd == '123':
            return index
        else:
            return login_failed
    res_func = login('wanglan','123')
    res_func()
    View Code

    4.函数名可以作为函数的参数

    def login():
        print('欢迎登陆')
    
    def index(auth):
        auth()
        print('欢迎来到首页')
    
    index(login)
    View Code

    闭包

    内部函数使用了外部函数的变量,内部函数就是一个闭包

    def func():
        name = 'wanglan'
        def inner():
            print(name)

    闭包常用的用法

    def func():
        name = 'wanglan'
        def inner():
            print(name)
        return inner
    f = func()
    f()
    View Code

    可以通过__closure__ 来查看是不是闭包,有值就是,没值就不是

    def func():
        name = 'wanglan'
        def inner():
            print(name)
        print(inner.__closure__)
        return inner
    f = func()
    f()
    View Code

    闭包嵌套

    def wrapper():    #1加载
        money = 1000
        def func():    #3.加载
            name = 'wanglan'
            def inner():  #6.加载
                print(name,money) #9.打印
            return inner  #7.返回内存地址
        return func   #4.返回内存地址
    f = wrapper()  #2.调用
    i = f() #5.调用
    i() #8.调用
    View Code

    匿名函数

    匿名函数:为了解决那些功能很简单的需求而设计的一句话函数

     def calc(n):
        return n ** n
    print(calc(10))
    
    # 换成匿名函数
    calc = lambda n: n ** n   #lambda:关键字   n:形参   n ** n :返回值,就是return后面的内容
    print(calc(10))
    View Code

    小结

    函数的定义规则

    1.定义:def 关键词开头,空格之后接函数名称和圆括号()。
    2.参数:圆括号用来接收参数。若传入多个参数,参数之间用逗号分割。
        参数可以定义多个,也可以不定义。
        参数有很多种,如果涉及到多种参数的定义,应始终遵循位置参数、*args、默认参数、**kwargs顺序定义。
        如上述定义过程中某参数类型缺省,其他参数依旧遵循上述排序
    3.注释:函数的第一行语句应该添加注释。
    4.函数体:函数内容以冒号起始,并且缩进。
    5.返回值:return [表达式] 结束函数。不带表达式的return相当于返回 None
    
    def 函数名(参数1,参数2,*args,默认参数,**kwargs):
            """注释:函数功能和参数说明"""
            函数体
            ……
            return 返回值
    View Code

    函数的调用规则

    1.函数名()
        函数名后面+圆括号就是函数的调用。
    2.参数:
        圆括号用来接收参数。
        若传入多个参数:
            应按先位置传值,再按关键字传值
            具体的传入顺序应按照函数定义的参数情况而定
    3.返回值
        如果函数有返回值,还应该定义“变量”接收返回值
        如果返回值有多个,也可以用多个变量来接收,变量数应和返回值数目一致
    
    无返回值的情况:
    函数名()
    
    有返回值的情况:
    变量 = 函数名()
    
    多个变量接收多返回值:
    变量1,变量2,... = 函数名()
    View Code

    命名空间

    一共有三种命名空间从大范围到小范围的顺序:内置命名空间、全局命名空间、局部命名空间
    小范围的可以用大范围的
    但是大范围的不能用小范围的
    范围从大到小(图)

    在小范围内,如果要用一个变量,是当前这个小范围有的,就用自己的
    如果在小范围内没有,就用上一级的,上一级没有就用上上一级的,以此类推。
    如果都没有,报错

    函数的嵌套:

      嵌套调用

      嵌套定义:定义在内部的函数无法直接在全局被调用

    函数名的本质:

      就是一个变量,保存了函数所在的内存地址

    闭包:

      内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数

     

  • 相关阅读:
    vscode settings
    AutomaticPrefetchPlugin
    echarts 文字超长换行
    webpack篇(三):serve启动 打印台友好提示
    webpack篇(二):webpack 5 (变化)
    webpack篇(一):webpack 5 热更新体验
    面试(保存一些面试相关的网址链接,方便之后复习)
    路由传递参数的常见的两种形式
    组件缓存注意事项 ---keep-alive
    从css属性和布局来说明一下,行类元素和行类块元素和块元素的区别
  • 原文地址:https://www.cnblogs.com/wanglan/p/9902453.html
Copyright © 2011-2022 走看看