Python中闭包,装饰器

221 阅读4分钟


目录

  1. 闭包
  2. 装饰器
  3. 相关类型参数
  • 闭包

    定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包。


def curve_pre(x):                    # 定义一个函数,其返回值是一个函数curve
                                    # 故当定义时相当于调用函数curve(闭包的特征)
     a = 25                         # 在外部作用于(父作用域)里定义变量
    def curve(x):                   # 在引用curve_pre函数时就定义了a变量
        return a * x * x
    return curve

a = 10                              # 函数体(父函数)外部变量,无法进入函数里
f = curve_pre()                     # 调用父函数
print(f(2))                         # 输入实参,输入子函数里

   

可以看出,闭包是由一个函数与外部环境定义的变量构成,此闭包在调用时不会受到外部变量的影响,闭包的意义是保存一个环境。

    用闭包实现累加算法:

    nonlocal 用法:


origin = 0

def factory(pos):

    def go(step):

        nonlocal pos                    # 定义这个pos不只是go函数里的pos,即第一次计算时可引用父函数里的pos
        new_pos = pos + step
        pos = new_pos                   # 通过pos储存先前的计算值
        return new_pos
    return go                           # 返回go函数(闭包)

tourist = factory(origin)               # 调用factory函数并赋值pos
print(tourist(2))                       # 把值传入step
print(tourist(3))
print(tourist(5))

#  输出2, 5, 10


  •   装饰器

  作用:
  1. 对于需要新增功能时,可以不改变原先函数内部的内容和调用的形式,在外面定义新增功能的装饰器,在用@引用装饰器。
  2. 装饰器可用于多个不同的函数,即定义一个新增功能,可以用于多种不同但需要此功能的函数里。

# 任务:新增打印时间的功能
import time()

def decorator(func):                  # 定义一个函数,其作用为增加新功能
                                      # 通过func形参把原先函数引入
    def wrapper():

        print(time.time())            # 输出新增的功能
        func()                        # 输出原函数的功能
    return wrapper                    # 返回子函数(闭包)

@decorator                            # 在原函数的定义前使用装饰器,即可新增原函数功能
def f1():
    print('This is a function')

f1()

# 输出:1578235993.4626515
        This is a function


  多参数函数的装饰器:使用包裹位置参数和包裹关键字参数


import time

def decorator(func):

    def wrapper(*args, **kw):                # *args为包裹位置参数
                                             # **kw为包裹关键字参数,接收所有关键字参数
        print(time.time())
        func(*args, **kw)
    return wrapper


@decorator
def f1(func_name):
    print('This is a function named' + func_name)

@decorator
def f2(func_name1, func_name2):
    print('This is two function named' + func_name1 + ',' + func_name2)

@decorator
def f3(func_name1, func_name2, **kw):
    print('This is two function named' + func_name1 + ',' + func_name2)
    pint(kw)

f1('卖小写')
f2('石敢当', '卖小邪')
f3('石敢当', '卖小邪', a = 1, b = 2, c = '123')

  • Python相关参数类型

 1.  位置参数:调用函数时根据函数定义的参数位置来传递参数,如前文的func_name1, func_name2


 2.  关键字参数:用于函数调用,通过“键--值”形式加以指定。可以让函数更加清晰,容易使用,同时也清除了参数的顺序需求。


def print_hello(name, sex):

    print('hello' + name + sex)

print_hello(sex = '男', name = '石敢当')        # 用关键字参数可以改变传入的位置

 

  3.  默认参数:用于定义函数,为参数提供默认值,调用函数时可传可不传该默认参数的值。

例:def(name = '石敢当', age, sex)


  4.  可变参数:定义函数时,有时我们不确定调用的时候会传递多少个参数,此时可以用包裹参数,来进行参数传递。

  • 包裹位置传递: *args 

   我们传进去的所有参数都会被args变量收集,他会根据传进参数的位置合并为一个元组,args是元组类型。

  •   包裹关键字传递: **kw

    kw是一个字典,收集所有关键字参数


    5. 解包裹参数: *和**也可以在函数调用的时候使用,称之为解包裹。

  • 在传递元组时,让元组的每一个元素对应一个位置参数

def print_hello(name, sex):

    print name, sex

args = ('石敢当', '男')
print_hello(*args)


  • 在传递字典时,让字典的每个键值作为一个关键字参数传递给函数

def print_hello(kw):

    print kw

kw = {'name' = '石敢当', 'sex' = '男'}
print_hello(**kw)



  • 最后,感谢观众老爷的浏览,下面是卖小邪的微信号,希望有志同道合的码友能够加下,也更希望有业界大佬来指导小憨憨的编程之路!!!

  • 感谢感谢