python函数式编程基础(一)

函数定义:
    @装饰器1
    @装饰器2
    ...
    def 函数名(位置形参, *元组形参, 命名关键字形参, **字典形参):
        """文档字符串"""

        语句块

正式介绍装饰前,先让我们学习一下闭包的概念:

闭包 closure:

    闭包是指引用了此函数外部嵌套函数作用域变量的函数
闭包必须满足3个条件:
    1.必须有内嵌函数
    2.内嵌函数必须引用外部函数中的变量
    3.外部函数返回值必须是“内嵌函数”

1.有如下函数,各方面测试已OK:

def decorated(x):
    print('x ** x = %d' % x ** x)
decorated(2)
decorated(3)
2.现在想在每次调用此函数前,均输出一次当前的时间,且不允许修改函数内部:
import time

def decorated(x):
    print('x ** x = %d' % x ** x)

def decorate(x):
    print("%d:%d:%d" % time.localtime()[3:6])
    decorated(x)

decorate(2)
decorate(3)
    此方法存在的一个问题是:如果原程序中多处调用了decorated函数,则需把每一处都修改为decorate,工作量很大。下面尝试在程序调用时无需修改原函数名:
import time

def decorated(x):
    print('x ** x = %d' % x ** x)

def decorate(func):
    print("%d:%d:%d" % time.localtime()[3:6])
    return func

decorated = decorate(decorated)
decorated(2)
decorated(3)

运行结果:
14:50:25
x ** x = 4
x ** x = 27

    此方法可以实现在程序调用时,无需修函数名;但仍存在一个非常严重的错误,decorated函数本身并未做任何改变,因此运行结果中,只在第一次调用次函数时打印一次时间,decorate函数只在decorated = decorate(decorated)赋值时运行一次。

3.为了解决2中存在的问题,我们可以借助闭包来实现:

import time

def decorated(x):
    print('x ** x = %d' % x ** x)

def decorate(func):
    def inner(x):
        print("%d:%d:%d" % time.localtime()[3:6])
        func(x)
    return inner

decorated = decorate(decorated)
decorated(2)
decorated(3)

运行结果:
14:58:36
x ** x = 4
14:58:36
x ** x = 27
    上述程序中,使用闭包实现了在不修改函数内部及调用程序的情况下,改变了原函数的功能。decorate函数内嵌了一个inner函数,且返回值为inner函数,并且inner函数访问了enclosing作用域变量func,形成了一个闭包。更值得庆幸的是,python中为了简化3中的写法,为我们提供了一个语法糖"@装饰函数",即装饰器:
import time

def decorate(func):
    def inner(x):
        print("%d:%d:%d" % time.localtime()[3:6])
        func(x)
    return inner

@decorate
def decorated(x):
    print('x ** x = %d' % x ** x)

decorated(2)
decorated(3)

运行结果:
15:8:36
x ** x = 4
15:8:36
x ** x = 27
装饰器:
    装饰器是一个函数,主要作用是用来包装另一个函数和类
    是在不改变原函数名(或类名)的情况下,改变被包装对象的行为

什么是函数装饰器
    1.函数装饰器是指装饰器是一个函数,传入的是一个函数,返回的也是一个函数
    2.函数一旦被装饰,它绑定的将是装饰器函数的返回值。

语法结构:
    def 装饰器函数名(函数名作为参数):
        语句块
        return 函数对象

    @装饰器函数名<换行>
    def 函数名(形参列表):
        语句块

函数装饰器的应用:
    def decorator_fun(fn):
        def fx():
            print("在函数original_fun调用之前,新增的处理程序!")
            fn()
            print("在函数original_fun调用之后,新增的处理程序!")
        return fx

    @decorator_fun
    def original_fun():
            print("此函数已经过测试,一切OK!")

    original_fun()
    备注:
        1.在程序开发过程中,一旦已经测试OK的函数,在后期如需新增功能时,应尽量避免去修改
        原函数,通常使用函数装饰器来完成。且使用函数装饰器,调用部分的的程序也无需修改。
        2.对于被装饰函数需要支持参数的情况,装饰器的内嵌函数须支持同样的签名
函数说明:
    1.函数本身可以赋值给变量,赋值后变量绑定函数
    2.允许将函数本身作为参数,传递给另一个函数
    3.允许函数返回一个函数
    4.应使用函数式编程思想,但程序中修改模块内部是大忌。

函数的4种形参定义方式:
    位置形参
    星号元组形参
    命名关键字形参
    双星号字典形参

     位置形参:
        语法:
            def 函数名(形参名1, 形参名2, ...):
                语句块
     星号元组形参:
        语法:
            def 函数名(*元组形参名):
                语句块
        作用:
            允许传入任意个位置实参
     命名关键字形参:
        语法:
            def 函数名(*, 命名关键字形参)
        或:
            def 函数名(*args,命名关键字形参)

        说明:
            强制所有的传参都必须使用关键字传参
     双星号字典形参:
        语法:
            def 函数名(**字典形参名):
                语句
        作用:
            允许传入任意个关键字实参

形参定义的顺序:
    位置形参
    星号元组形参
    命名关键字形参
    双星号字典形参

函数的文档字符串:
    语法格式:
        def 函数名(形参列表)
            """函数的文档字符串"""
            函数语句块
    示例:
        def func():
            '''此函数用来打招呼...
            这是函数的文档字符串
            '''
            pass
        可在交互模式下输入如下命令,查看函数的文档字符串:
            >>>import 模块名
            >>>help(模块名.func)
    说明:
        文档字符串用来说明本函数的功能和使用方法,方便程序的阅读和后期维护

函数的__doc__属性:
    备注:
        所有系统定义的特殊含义的标识符使用的是双下划线,为了避免与用户定义的标志负产生冲突
    作用:
        用于记录文档字符串
    操作:
        >>>max.__doc__

        >>> import 模块名
        >>> 模块名.函数名.__doc__

函数的__name__属性:
    作用:
        用于记录函数的名称

函数的4中实参传递方式:
    位置传参 / 序列传参(字符串,列表,元组)
    关键字传参 / 字典关键字传参
    
     位置传参:
        实参与形参的对应关系按位置来依次对应
        def func(a, b, c):
            ...
        func(1, 2, 3)
    序列传参:
        函数在调用过程中用 “*” 将序列拆解后按位置进行传递的传参方式
        def func(a, b, c):
            ...
        s = "ABC"
        L = [4, 5, 6]
        t = (1.1, 1.2, 1.3)
        func(*s)
        func(*L)
        func(*t)
     关键字传参:
        按着形参的名称给形参赋值;实参和形参按名称进行匹配
     字典关键字传参:
        将字典用 “**” 拆解后进行关键字传参的传参方式
        def func1(a, b, *, c, d):
            ...
        def func2(a, b, *args, c, d):
            ...
        func1(1, 2, c=300, d=400)
        func2(1, 2, 3, 4, c=300, d=400)
        func2(1, 2, 3, 4, **{'d':400, 'c':300})
     综合传参:
        1.函数的传参方式确定形参能唯一匹配到相应的实参。
        2.位置传参在前,关键字传参在后



猜你喜欢

转载自blog.csdn.net/geroge_lmx/article/details/80740484
今日推荐