首页 > 编程语言 >Python系列(6)- Python 函数、Python 装饰器

Python系列(6)- Python 函数、Python 装饰器

时间:2024-08-22 19:05:31浏览次数:11  
标签:__ 函数 Python 参数 func print 装饰


函数在数学上的定义:给定一个非空的数集 A,对 A 施加对应法则 f,记作 f(A),得到另一数集 B,也就是 B = f(A),那么这个关系式就叫函数关系式,简称函数。

简而言之,两个变量 x 和 y,如果每给定 x 的一个值,y 都有一个确定的值与其对应,那么我们就说 y 是 x 的函数。其中,x 叫做自变量,y 叫做因变量。

函数的抽象定义:一个输入产生一个输出,那么这个输出就是输入的函数,输入和输出之间的这种关系叫做函数映射。

计算机函数(或称为程序函数、子程序等)是编程中的一个重要概念,它封装了一段代码,用于完成特定的任务或计算。计算机函数可以接受输入(参数),执行一系列操作,并返回结果(如果有的话)。计算机函数的设计旨在提高代码的重用性、可读性和可维护性。

计算机函数和数学函数都描述了一种 “输入-> 输出” 的对应关系。在数学中,这种对应关系是抽象的、理论的;在计算机中,这种对应关系是通过具体的代码实现的。

‌数学函数‌通常遵循严格的数学规则和逻辑,其定义和性质是独立于具体实现方式的。‌计算机函数‌则依赖于具体的编程语言、算法和数据结构来实现。计算机函数可能需要对数学函数进行近似、离散化或优化,以适应计算机的计算能力和存储限制。

 

1. Python 函数

    Python 函数是计算机函数的一种具体实现,它们在概念和功能上与计算机函数相似,但 Python 提供了更多的灵活性和高级功能,使得程序员能够以更加模块化和可重用的方式组织代码‌。

    在 Python 语言中,函数是组织和重用代码的基本方式之一。
    
    Python 函数具有以下特性:

        (1) 函数是组织代码的方式,使得代码更加模块化和可重用。
        (2) 函数可以接受输入参数,这些参数可以是必需的、默认的或可变数量的。
        (3) 函数可以有返回值,函数执行完毕后可以返回结果。
        (4) 函数可以有文档字符串,用于描述函数的功能和使用方法。
        (5) 函数是 Python 面向对象编程中方法的基本单元。

   Python 函数的主要作用:

        (1) 代码重用:函数可以将一段代码封装起来,以便在多个地方重复使用。这样可以提高代码的复用性,减少代码的冗余。
        (2) 模块化编程:函数可以将复杂的程序分解成多个小的模块,每个模块负责完成一个特定的功能。这样可以使程序结构更加清晰,易于维护和扩展。
        (3) 提高代码可读性:函数可以将一段代码命名为一个有意义的名称,使代码更易于理解和阅读。函数还可以添加注释,进一步解释代码的作用和实现方式。
        (4) 提高代码的可维护性:函数可以将一段代码封装起来,使其成为一个独立的单元。这样在修改和调试代码时,只需要关注函数的实现细节,而不需要关心其他部分的代码。
        (5) 提高代码的可测试性:函数可以独立于其他代码进行测试,这样可以更方便地验证函数的正确性。通过编写测试用例,可以快速发现和修复函数中的错误。


2. 函数的定义和调用

    Python 定义函数使用 def 关键字,语法格式如下:

        def 函数名([参数列表]):
            功能代码
            [return [返回值]]

        名词解释:

            (1) 函数名:一个符合 Python 语法的标识符,函数名要能够体现出该函数的功能;
            (2) [参数列表]:可选项,多个参数之间用逗号分隔,这里的参数就是形参;
            (3) [return [返回值] ]:可选项,返回值可以是各种数据类型,可以返回多个值,各值用逗号分隔。
            
            注:[] 括表示非必选项。

    调用函数(即执行函数),语法格式如下:

        [变量] = 函数名([参数列表])

        名词解释:

            (1) 函数名: 就是定义函数时的函数名;
            (2) [参数列表]: 可选项,多个参数之间用逗号分隔,这里的参数就是实参;
            (3) [变量]: 可选项,如果函数没有返回值,可以不定义变量接收返回值。

    示例:

        #!/usr/bin/python3

        def func(a, b):
            return a+b,a-b

        if __name__ == "__main__":

            c, d = func(1, 2)
            print(f'a + b = {c}')
            print(f'a - b = {d}')

 

    输出结果如下:

        a + b = 3
        a - b = -1


3. 函数参数

    1) 位置参数
    
        位置参数 (或称必选参数),是指必须按照正确的顺序将实际参数传到函数中,即调用函数时传入实际参数的数量和位置都必须和定义函数时保持一致。

        示例:

            #!/usr/bin/python3

            def func(a, b):
                return a+b

            if __name__ == "__main__":

                c = func(1, 2, 3)
                print(f'a + b = {c}')


        输出结果如下:

            Traceback (most recent call last):
            File "d:/pythonDemo/func.py", line 8, in <module>
                c = func(1, 2, 3)
            TypeError: func() takes 2 positional arguments but 3 were given

        注:func 需要 2 个参数,调用 func 时传了 3 个参数。
        
    2) 默认参数

        Python 函数可以为参数设置默认值,即在定义函数时,直接给形参设置一个默认值。调用函数时没给设置了默认值的形参传值,该参数自动使用设置的默认值。

        示例:

            #!/usr/bin/python3

            def func(a, b=3):
                return a+b

            if __name__ == "__main__":

                c = func(1, 2)
                print(f'a + b = {c}')

                d = func(1)
                print(f'a + b = {d}')


        输出结果如下:

            a + b = 3
            a + b = 4

            注:带默认值的参数必须处于不带默认值的参数的后面(从左到右排序)

        可以使用 “函数名.__defaults__” 查看函数参数的默认值,其返回值是一个元组。执行如下代码:

            print(func.__defaults__)

        输出结果如下:

            (3,)

    3) 可变参数

        可变参数 (或称不定长参数),即参数的数量是弹性的,不必在声明函数时对所有参数进行定义,用循环实现,在形参前加一个星号 *,则可以表示该参数是一个不定长参数。
        
        示例:

            #!/usr/bin/python3

            def func(*params):
                print(params)

            if __name__ == "__main__":

                func(1)
                func(1, 2, 3)
                func(*[4,5,6])


        输出结果如下:        

            (1,)
            (1, 2, 3)
            (4, 5, 6)

        注:形参前面带 *,表示可变参数;实参前面带 *,表示 * 后面必须是一个 list 或 touple,比如:func(*[4,5,6]) 等效于 func(4,5,6) 。

    4) 关键字参数

        关键字参数是根据形参的名字来确定输入的参数值。函数调用传递实参时,不需要与形参的位置完全一致,只要将形参的名称写正确即可。

        示例:

            #!/usr/bin/python3

            def func(name, age, **description):
                print('name: ', name, ' age: ', age, ' description: ', description)

            if __name__ == "__main__":

                func(age=18, name='Python', city='Shanghai', job='Engineer')
                func(age=20, name='Java', **{'city': 'Beijing', 'job': 'Designer'})


        输出结果如下:        

            name: Python age:  18  description: {'city': 'Shanghai', 'job': 'Engineer'}
            name: Java age:  20  description: {'city': 'Beijing', 'job': 'Designer'}

        注:形参前面带 **,表示关键字参数, 以 key=value 的格式输入;实参前面带 **, 表示 ** 后面必须是一个 dict 。

    5) 命名关键字参数

        一个特殊分隔符 * 参数,该参数后面的参数被视为命名关键字参数。

        示例:

            #!/usr/bin/python3

            def func(name, age, *,city, job):
                print('name: ', name, ' age: ', age, ' city: ', city, ' job:', job)

            if __name__ == "__main__":

                func('Python', 18, city='Shanghai', job='Engineer')


        输出结果如下:        

            name:  Python  age:  18  city:  Shanghai  job: Engineer

            注:如果第3个 * 参数本身就是一个可变参数 (带 *),该可变参数后面的参数就是命名关键字参数,无需再添加单独的 * 参数。

    6) 参数组合使用

        在 Python 中定义函数,可以用位置参数、默认参数、可变参数、关键字参数和命名关键字参数,这 5 种参数都可以组合使用。

        参数定义的顺序是(从左到右排序):位置参数、默认参数、可变参数、命名关键字参数和关键字参数。   

        示例:

            #!/usr/bin/python3

            def func(a, b=3, *params, name, age):
                print(params)
                print('name: ', name, ' age: ', age)
                return a+b

            if __name__ == "__main__":

                c = func(1, 2, *[4, 5, 6], name='Python', age=9)
                print(f'a + b = {c}')


        输出结果如下:

            (4, 5, 6)
            name: Python age:  9
            a + b = 3

    7) 值传递和引用传递

        在 Python 中,根据实际参数的类型不同,函数参数的传递方式可分为 2 种,分别为值传递和引用(地址)传递:

            (1) 值传递:适用于实参类型为不可变类型(字符串、数字、元组);
            (2) 引用(地址)传递:适用于实参类型为可变类型(列表,字典);

        值传递和引用传递的区别是,函数参数进行值传递后,若形参的值发生改变,不会影响实参的值;而函数参数继续引用传递后,改变形参的值,实参的值也会一同改变。

        示例:

            #!/usr/bin/python3
            # -*- coding: UTF-8 -*-

            def func(p1, p2, p3, p4, p5):
                p1 = 'Hello Python2'
                p2 = 9
                p3 = (7,8)
                p4[1] = 'age2'
                p5['city'] = 'Beijing'

            if __name__ == "__main__":
                v1 = 'Hello Python'
                v2 = 1
                v3 = (2,3)
                v4 = ['name1', 'name2']
                v5 = { 'city': 'Shanghai'}

                print(v1)
                print(v2)
                print(v3)
                print(v4)
                print(v5)

                func(v1, v2, v3, v4, v5)

                print(v1)
                print(v2)
                print(v3)
                print(v4)
                print(v5)


        输出结果如下:

            Hello Python
            1
            (2, 3)
            ['name1', 'name2']
            {'city': 'Shanghai'}
            Hello Python
            1
            (2, 3)
            ['name1', 'age2']
            {'city': 'Beijing'}

 

4. 特殊函数

    1) lambda 表达式(匿名函数)

        lambda 表达式,又称匿名函数,常用来表示内部仅包含 1 行表达式的函数。如果一个函数的函数体仅有 1 行表达式,则该函数就可以用 lambda 表达式来代替。

        lambda 表达式的格式如下:

            name = lambda [list] : 表达式

        定义 lambda 表达式必须使用 lambda 关键字,[list] 作为可选参数(等同于函数的参数列表),name 为该表达式的名称。

        示例:

           #!/usr/bin/python3

            if __name__ == "__main__":

                addsub = lambda a,b:(a+b,a-b)
                c,d = addsub(1, 2)
                print(f'a + b = {c}')
                print(f'a - b = {d}')


        输出结果如下:

            a + b = 3
            a - b = -1

        lambda 表达式,其就是简单函数(函数体为单行的表达式)的简写版本。对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁。对于不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高程序执行的性能。

    2) 局部函数

        Python 支持在函数内部定义函数,此类函数称为局部函数,或称为嵌套函数。

        示例:

            #!/usr/bin/python3
            # -*- coding: UTF-8 -*-

            def func(n):
                # 局部函数定义
                def inner_func():
                    return f'Local function inner_func({n})'
                
                # 局部函数调用
                return inner_func()

            if __name__ == "__main__":
                f1 = func(1)
                f2 = func(2)
                print(f1)
                print(f2)


        输出结果如下:

            Local function inner_func(1)
            Local function inner_func(2)

            注:func(n) 函数被调用时,func(n) 调用了其内部的局部函数 inner_func(),inner_func() 读取和使用了 n 的实时值,生成字符串返回值。

    3) 闭包函数

        闭包函数(或称闭合函数,又称闭包),闭包函数是一个局部函数,它的不同之处在于,闭包返回的不是值,而是一个函数引用(或指针)。

        示例:

            #!/usr/bin/python3
            # -*- coding: UTF-8 -*-

            def func(n):
                # 闭包函数定义
                def inner_func():
                    return f'Local function inner_func({n})'
                return inner_func

            if __name__ == "__main__":
                f1 = func(1)
                f2 = func(2)
                print(f1())   
                print(f2())
                
                print(f1.__closure__)
                print(f2.__closure__)


        输出结果如下:

            Local function inner_func(1)
            Local function inner_func(2)
            (<cell at 0x0000025A01282730: int object at 0x00007FFA011D16A0>,)
            (<cell at 0x0000025A012826D0: int object at 0x00007FFA011D16C0>,)

            注:func(n) 函数被调用时,func(n) 没有调用其内部的闭包函数 inner_func(),就返回函数引用,这里我们把函数引用赋值给 f1、f2。

                闭包函数的运行代码中,包含了 func(n) 的形参 n,闭包机制自动把 n 的实时值保存到函数引用的 __closure__ 属性。
                
                当 f1 和 f2 被作为函数运行时,f1 和 f2 自动从各自的 __closure__ 属性读取对应的 n 的实时值。


5. Python 装饰器

    装饰器(decorator)是 Python 中的一种高级功能,它允许你动态地修改函数或类的行为。Python 装饰器是一种语法糖,本质上是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。

    Python 提供了一些内置的装饰器,比如 @property、 @staticmethod 、@classmethod 等。

    装饰器的应用场景:

        日志记录: 装饰器可用于记录函数的调用信息、参数和返回值。
        性能分析: 可以使用装饰器来测量函数的执行时间。
        权限控制: 装饰器可用于限制对某些函数的访问权限。
        缓存: 装饰器可用于实现函数结果的缓存,以提高性能。

    定义/使用装饰器,语法格式如下:

        # 定义装饰器
        def decorator_function(original_function):
            def wrapper(*args, **kwargs):
                # 调用原始函数前添加的新功能
                before_call_code()
            
                result = original_function(*args, **kwargs)
            
                # 调用原始函数后添加的新功能
                after_call_code()
            
                return result
            return wrapper

        # 使用装饰器
        @decorator_function
        def target_function(arg1, arg2):
            pass  # 函数的实现


    名词解释:

        decorator_function: 自定义的装饰器名称,也是一个装饰器函数。
        original_function:装饰器函数的参数,它是一个函数引用(地址)
        wrapper:装饰器函数内的一个内部函数,执行一些功能操作,然后调用 original_function,并返回结果。
        @decorator_function:@ 符号 + 装饰器名称,表示要把该装饰器运用到 target_function 函数,Python 会自动将 target_function 作为参数传递给装饰器函数 decorator_function
        target_function:就是装饰器要装饰的函数。

    示例,做一个 time_logger 装饰器,自动给每行 log 前面添加时间戳:

        #!/usr/bin/python3
        # -*- coding: UTF-8 -*-

        import time

        def time_logger(func):
            def wrapper(*args, **kwargs):
                l = list(args)
                if l:
                    l[0] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + ' | ' + l[0]

                result = func(*l, **kwargs)
                return result
            return wrapper


        @time_logger
        def logger(s):
            print(s)

        if __name__ == "__main__":
            logger('start service')
            time.sleep(1)
            logger('stop service')


    输出结果如下:

        2024-08-20 16:08:23 | start service
        2024-08-20 16:08:24 | stop service

标签:__,函数,Python,参数,func,print,装饰
From: https://www.cnblogs.com/tkuang/p/18374532

相关文章

  • python03-标准库 第三方库-pathlib模块
    python标准库:Python自带的一组模块和库,这些模块和库提供了Python编程所需的基础功能和工具https://docs.python.org/zh-cn/3/library/index.html?eqid=8ca0b3ea000067990000000264800802Python包索引:即PyPI(PythonPackageIndex),是一个仓库,存放了许多可以通过pip安装的独......
  • set 的详细用法(set 排序、set 的遍历、set 的多种倒序遍历方法、set 的基本成员函数)
    目录一:set的简介二:set的使用(要包含头文件)1.set的定义2.set的基本成员函数3.set的遍历(1)迭代器iterator(即升序输出)(2)倒序输出1.rbegin()和rend()2.当然,也可以逆向思维一下。​^^3.用greater实现降序排列三:应用基本成员函数的代码【总结】有上述代码可以看出,插......
  • python模块之psutil
    模块介绍psutil是一个Python的跨平台库,用于获取系统和进程的运行状态以及实时信息。它能够方便地访问系统的CPU、内存、磁盘、网络等资源的使用情况。此外,psutil也能够管理和监控进程,非常适合用于系统监控和性能分析等应用。psutil库适用于Python3.x版本,自版本5.0.0起......
  • Python中matplotlib使用4
    在matplotlib中,可以通过绘制“饼图”来展示各类别在总体中所占的比例。1绘制基本“饼图”通过matplotlib中的pie()函数绘制饼图,代码如图1所示。图1绘制基本“饼图”的代码从图1中可以看出,pie()函数的参数y即为要绘制的数据,绘制出的“饼图”如图2所示。图2基本“饼图......
  • Python中定义和使用类的私有属性和方法
    类的私有属性和方法指的是只能在类的内部使用,而不能在类外使用的属性和方法。1单下划线方式在定义类的属性和方法时,在名字前面加一个下划线,此时表示该属性或方法只能在类的内部使用,而不能在类的外部使用,代码如图1所示。图1定义类的私有属性从图1中可以看出,在类Myclass中......
  • Python中类的使用4
    在Python中,如果要编写的类是另一个类的特殊版本,可以使用继承。一个类A继承另一个类B,类A将自动获得类B的所有属性和方法,类B叫做父类,而类A叫做子类。假设有一个类是表示“人”的类,而另一个类是表示“学生”的类,因为“学生”是“人”的特殊版本,因此可以把表示“人”的类当作父类,表......
  • python3脚本批量重命名歌曲文件
    场景:歌曲文件名有些混乱 于是想用个脚本批量重命名这些歌曲文件,可以选择【歌曲名-歌手】或【歌手-歌曲名】规范这些文件名脚本如下:importosimportrefrommutagen.id3importID3,TIT2,TPE1frommutagen.mp4importMP4#替换后歌手分隔符REPLACEMENT_STRING......
  • 【整理快速通道】python语法import速查
    这段文字是特意发送在除了CSDN以外的其他网站的,如果这段文字出现在CSDN里面,则说明该账号为抄袭账号,关键字索引:抄袭千思的文章目录正文文件夹结构模块调用包内模块1.import2.from...import...3.import...as4.from...import*(不推荐)同级两个模块导入from...import动态导入try.......
  • python对于pyinstaller使用的一些随记
    1.虚拟环境中需要安装对应的pyinstaller  pipinstallpyinstaller(该命令后会安装pyinstaller和pyinstaller-hooks-contrib)注意:如果在当前环境下没有pyinstaller,则会在本机电脑的环境变量中的path中去寻找,如果没有则报错。      此处设置可参考:https://blog.csdn.......
  • Python 实现批量数字二维码生成器
    Python实现批量数字二维码生成器创建时间:2024-08-09一、背景手动逐个生成特定格式和内容的二维码是一项繁琐且耗时的任务。虽然有写二维码工具也可以制作,但是往往有一些限制,为了能够高效、批量生成自定义二维码的需求,开发了这个基于Python的数字二维码生成器应用程序。在实......