• python函数学习总结


    函数

    一、函数定义

    python中用def关键字来定义函数

    def fun(形参列表):
        语句块
    

    二、形参,实参

    形参:形式参数,在定义函数时括号中定义的参数

    实参:实际参数,在调用函数时实际传入的参数

    三、传参

    python的传参采用的是一种“传对象引用”的方式,传参传的是对象的引用,如果传的是不可变对象,在函数中改变参数的值时,会创建新的对象,并不会改变原始对象,相当于“值传递”;如果传的时可变对象,在函数中改变参数的值时,会直接修改原始对象,相当于“传引用

    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    def fun(n,l):
        n += 1
        l.append(10)
        print("不可变对象-修改后的对象%s"%n)
        print("可变对象-原对象%s"%l)
    
    if __name__ == "__main__":
        a = 1
        list1 = [1,2,3,4]
        fun(a,list1)
        print("不可变对象-原对象%s"%a)
        print("可变对象-原对象%s"%list1)
    

    执行结果:

    不可变对象-修改后的对象2
    可变对象-原对象[1, 2, 3, 4, 10]
    不可变对象-原对象1
    可变对象-原对象[1, 2, 3, 4, 10]
    

    四、参数类型

    1、位置参数(传实参时):

    比传参数

    传递实参的数量和位置必须和定义时的形参一一对应

    2、关键字参数(传实参时)

    比传参数

    采用“形参名=实参”的方式传递实参,这种方式不需要与定义时的形参位置一一对应,python会自动根据形参名匹配

    注意:关键字参数必须在位置参数后面

    3、默认参数(定义形参时)

    非比传参数

    在定义形参时就要为其设置默认值,可以传参也可以不传参,对变化较小的参数可以定义成默认参数

    注意:

    1、默认参数在定义时应该放在形参的右面

    2、默认参数同城应该定义成不可变类型

    4、可变长参数

    非比传参数

    可变长参数指的是参数的个数不固定

    由于传实参有按位置和按关键字两种方式,所以可变长参数也有两种

    4.1、*args

    定义形参时在参数名前加一个“”号,通常用args表示

    它把传入的元素存放在一个元祖里,不限制传入参数的个数,用作参数比较多的时候

    在传实参时,可以传递多个值,也可以传入一个元祖(列表、range(x))前面加一个“*****”

    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    def fun(*args):
        print(args)
        print(type(args))
    
    if __name__ == "__main__":
        a = 1
        list1 = [1,2,3,4]
        fun(1,2,3,4)
        fun(*list1)		#列表前必须加*
        fun(*range(10))
    

    4.2、**kwargs

    定义形参时在参数名前加两个“*”号,通常用**kwargs表示

    它把传入的元素存放在一个字典里

    在传实参时,可以传递多个值必须时k=v的形式,也可以传入一个字典前面加两个“*****”

    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    def fun(**kwargs):
        print(kwargs)
        print(type(kwargs))
    
    if __name__ == "__main__":
        fun(a=1,b=2,c=3)
        dict1 = {"a":1,"b":2,"c":3}
        fun(**dict1)		#字典前必须加**
    

    4.3、(*args,**kwargs)

    (*args,**kwargs)表示可以传递任何类型任何数量的参数

    5、命名关键字参数

    定义形参时,在必传参数后面以“”分割,后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递

    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    def fun(a,b,*,c,d):
        print(a,b,c,d)
    if __name__ == "__main__":
        fun(1,2,c=3,d=4)		#c和d必须以k=v的形式传参,否则报错
    

    6、参数的组合使用

    如果一个函数中要使用多种参数

    必传参数+默认参数+*args+命名关键字参数+**kwargs

    五、函数的返回值 return语句

    return语句用来给定函数的返回值,并结束函数

    一个函数中可以有多个return语句,但最多只有一个会生效

    如果函数没有return语句,则默认返会None

    六、嵌套函数

    函数内定义函数,就是嵌套函数

    内函数只能在外函数内部调用

    def one():
        def two():	#定义内函数
            pass
        two()		#调用内函数
    

    七、命名空间和作用域

    1、命名空间

    命名空间:从python解释器开始执行之后,就在内存中开辟了一个空间,每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来。但是当遇到函数定义的时候解释器只是象征性的将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑解释器根本不关心。等执行到函数调用的时候,python解释器会再开辟一块内存来存储这个函数里的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量会存储在新开辟出来的内存中。函数中的变量只能在函数的内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。

    三种命名空间

    • 内置名称:Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等
    • 全局名称:模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量
    • 局部名称:函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量

    命名空间的生命周期

    命名空间的生命周期取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束

    无法从外部命名空间访问内部命名空间的对象

    命名空间的加载顺序

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

    命名空间的查找流程

    • 系统每次执行一个函数时,就会创建新的局部命名空间
    • 局部命名空间代表一个局部环境,其中包含函数参数的名称和在函数体内被赋值的变量名称
    • 解析名称时,解释器将首先搜索局部命名空间,如果没有找到匹配的名称,就会搜索全局命名空间
    • 如果在全局命名空间未找到,则搜索内置命名空间。如果仍然找不到,就会引发NameError异常

    2、作用域

    作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域

    全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

    局部作用域:局部名称空间,只能在局部范围内生效

    3、局部变量,全局变量

    局部变量:在局部作用域内定义的变量(函数内部定义

    全局变量:在函数外定义的变量(python文件内一般顶格定义的变量)

    4、不同作用域的变量访问原则

    • 内部作用域可以访问外部作用域的变量,但不能对外部作用域的变量重新赋值(函数内可以获取到外部变量的值,但不能重新赋值)
    • 外部作用域无法访问内部作用域的变量

    5、global、nonlocal

    global:在函数中通过global关键字声明某个变量时全局变量,可以在函数内对全局变量重新赋值

    nonlocal:在嵌套函数中,内部函数要重新对外部函数中的变量赋值,需要先用nonlocal关键字声明

    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    
    a = 1   #定义全局变量a
    
    def func():
        print(a)    #访问全局变量a
        global a    #声明a是全局变量
        a = 2   #修改全局变量a
        
    if __name__ == "__main__":
        print(a)
        func()
        print(a)
    
    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    
    def one():
        a = 1   #定义外部函数变量a
        def two():
            print(a)    #访问外部函数变量a
            nonlocal a  #声明a时外部函数变量
            a += 1      #为外部函数变量a重新赋值
            print(a)
        
        two()       #调用内部函数
        print(a)
    
    if __name__ == "__main__":
        one()
    

    八、高价函数

    一个函数可以作为参数传递给另一个函数,或者一个函数的返回值为另一个函数(若返回值是该函数本身,则为递归),满足任一条件则为高价函数

    1、参数为函数

    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    
    def func(l):     #传入一个列表
        for i in l:
            print(i)
    
    def test(fun,l):
        fun(l)
    
    if __name__ == "__main__":
        test(func,[1,2,3,4,5,6])
    

    2、返会值为函数

    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    
    def func(l):     #传入一个列表
        for i in l:
            print(i)
    
    def test():
        return func
    
    if __name__ == "__main__":
        list1 = [1,2,3,4,5,6]
        a = test()
        a(list1)
    

    九、闭包

    • 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为
    • 内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包

    形成闭包的条件:

    • 必须有一个嵌套函数(函数内部的函数)
    • 内部函数必须引用外部函数中定义的变量
    • 外部函数必须返回内部函数
    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    
    def one(l):
        a = 1
        def two():
            #nonlocal a,l    如果内函数内要对外函数的变量重新赋值,则需要用nonlocal声明
            s = a * l
            print(s)
        return two
    
    if __name__ == "__main__":
        l = 10
        fun = one(l)
        fun()
    

    十、装饰器

    装饰器的本质:是一个闭包函数

    装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

    一个装饰器

    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    import time
    def times(fun):
        def inter(*args,**kwargs):
            starttime = time.time()
            print("%s开始执行"%fun.__name__)
            res = fun(*args,**kwargs)
            stoptime = time.time()
            print("%s执行结束"%fun.__name__)
            print("%s的执行时间为%2f"%(fun.__name__,stoptime-starttime))
            return res
        return inter
    
    @times
    def test(a,b):
        print(a + b)
    
    if __name__ == "__main__":
        test(3,5)
    
    

    多个装饰器修饰一个函数

    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    
    def test1(fun):
        def inner(*args,**kwargs):
            print("第一个装饰器开始")
            res = fun(*args,**kwargs)
            print("第一个装饰器结束")
            return res
    
        return inner
    
    def test2(fun):
        def inner(*args,**kwargs):
            print("第二个装饰器开始")
            res = fun(*args,**kwargs)
            print("第二个装饰器结束")
            return res
        return inner
    
    @test1	#test1(test2(fun))
    @test2	#test2(fun)
    def test(a,b):
        print(a + b)
    
    if __name__ == "__main__":
        test(3,5)
    
    

    多个装饰器装饰一个函数,装饰器从下到上依次执行

    十一、匿名函数 lambda

    • python使用lambda来创建匿名函数
    • lambda时一个表达式,比def简单很多,只能封装有限的逻辑
    • lambda有自己的命名空间,lambda表达式不能使用golbal和nonlocal(不能使用外部局部变量和全局变量)

    语法:

    lambda 参数列表 : 表达式(返回值)
    
    >>> f = lambda x : x ** 2
    >>> f(10)
    100
    
    #! /usr/bin/python3
    # -*- congfig:utf-8 -*-
    
    def test(l):
        f = map(lambda x: x ** 2,l)
        for i in f:
            print(i)
    
    if __name__ == "__main__":
        test(range(10))
    
  • 相关阅读:
    HashMap的实现原理
    LinkedHashMap的实现讲解
    ConcurrentHashMap原理分析
    javax.mail Java Extension(扩展)
    Singleton 单例模式
    Java序列化与反序列化(实践)
    Java IO操作
    Java NIO与IO的区别和比较
    java模拟异步消息的发送与回调
    java如何实现多个线程并发运行
  • 原文地址:https://www.cnblogs.com/jingxindeyi/p/13511220.html
Copyright © 2020-2023  润新知