Python 知识体系补全(闭包、装饰器、关键字参数**kwargs,位置参数*args)

本文介绍了Python中的闭包概念,即在函数内部定义并引用外部函数变量的函数。闭包常用于实现装饰器,后者是一种扩展函数功能的机制,可以在不修改原函数代码的情况下添加新功能。文章还提到了range和xrange函数的差异,以及*args和**kwargs在处理可变参数时的作用。装饰器通过返回一个局部函数对象来实现其功能,而语法糖如`@decorator`则简化了装饰器的使用方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

闭包:
    什么是闭包,一句话,在函数中再嵌套一个函数,并且引用外部函数的变量,这就是一个闭包了
    一般外部函数的返回值为内部函数
     def outer(x):
         def inner(y):
             return x + y
        return outer     # 外部函数的返回值,是内部函数 
     print(outer(6)(5))
    python 循环中不包含域的概念
        range() 函数饭返回一个可迭代对象(类型是对象)
        xrange() 与range类似,只是返回一个“xragne object” 对象,而非数组list
        要生成很大的数字序列的时候,用xrange回避range性能优很多,因为不需要一上来就开辟一块很大的空间。
装饰器:
     装饰器就是一个闭包,装饰器是闭包的一种应用,python装饰器就是用于拓展原来函数功能一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能,使用时在需要的函数前加上@xx
     #定义了一个函数
def foo():
#函数功能
    print("------1-------")
#定义了另一个函数传入了一个形参
def bar(func):      # 这里啊 func == foo    是 Ture
    #这段代码在干什么
    func()          # func() == foo()    #打印func()  其实就是  foo()
#python的函数可以像普通变量一样作为参数传递给函数,将函数foo 作为bar函数的实参
bar(foo)   # 这边接受的是foo函数,要使用函数不应该是  foo()  如果你知道多线程 中有一个分配线程
           # def test1()
           #      print('-----1------')
           # threading.Thread(target = test1)    # 主线程会分配一个子线程给去执行test1  函数 ,主线程会在这里等待 子线程执行完毕后死掉
    装饰器的本质是一个python函数或类,它可以让其他函数或者类在不需要做任何代码的前提下增加额外的功能,装饰器的返回值也是一个函数/类对象
    def use_logging():

        def wrapper():
            pass
        return wrapper   # 返回的只是局部函数的对象并不会执行内部函数的中代码

        def foo():
            print('i am foo')
        # 执行use_logging() 返回局部函数对象
        use_logging()   
            <function __main__.use_logging.<locals>.wrapper()>   # 函数对象

        def use_logging(func):   # func 形参

            def wrapper():
                print("--------1----------")
                # # logging.warn("%s is running" % func.__name__)
                # return func()   # 把 foo 当做参数传递进来时,执行func()就相当于执行foo()
            return wrapper   # 返回的只是局部函数的对象并不会执行内部函数的中代码

        def foo():
            print('i am foo')
        #use_logging() [执行效果] ==  返回 wrapper
        foo = use_logging(foo)    # foo 实参  foo 是函数foo 用变量foo接受                               # use_logging(foo)  == wrapper
        foo()   foo()  != 函数foo()   根据51行  所以得出  foo()  == wrapper()   # 它就会返回执行结果 --------1----------
        def use_logging(func):

            def wrapper():
                print("--------1----------")
                # # logging.warn("%s is running" % func.__name__)
                return func()   # 把 foo函数    当做参数传递进来时,执行func()就相当于执行foo()
                # 因此返回了func()  就会去执行 函数foo 中的print('i am foo') 所以打印结果 i am foo
            return wrapper   # 返回的只是局部函数的对象并不会执行内部函数的中代码

        def foo():
            print('i am foo')
        foo = use_logging(foo)   # use_logging(foo)  == wrapper
        foo()
语法糖:
    @ 就是语法糖的标识符  语法糖必须加在你想被作用的函数前面
    例如: 
         @use_logging
         def foo():
            print("i am foo")
    在下面的代码中 
        def use_logging(func):

        def wrapper():
            logging.warn("%s is running" % func.__name__)
            return func()
        return wrapper 
        语法糖的作用返回了 wrapper 
        @use_logging
        # 给函数foo 添加了语法糖use_logging
        def foo():
            print("i am foo")

        foo() #执行foo 函数其实也执行了语法糖use_logging
        #foo()  -  先去执行use_logging(foo)
        。。。。。。
        #暂时理解滞缓
语法糖提高程序的重复利用性 并增加了程序的可读性

*args、**kwargs
args 和 kwargs 通常还会在前面加上一两个星号,其实这是python开发人约定的变量名
其中args 是 arguments 的缩写,表示位置参数,kwargs 是keyword arguments 的缩写, 表示关键字参数这其实python中可变参数的两种形式,而且*args必须放在**kwargs的前面,因为位置参数在关键字参数的前面。
        # 使用这段函数必须清楚元组可以进行遍历
        def test_args(first,*args):
            print('-----1-----',first)
            print(type(args))
            print(args)
            for v in args:
                # 这里的[1,2,3,4]  作为元组的一个元素,这里的元组样式是 ([1,2,3,4],)
                print('-----2----',v)

        test_args(1,[2,3,4],4)
        #得出原因了吧
        for i in ([1,2,3,4],):
            print(i)   
    
    #经过测试 args 接受一个不定参数的元组     
   **kwargs 允许你讲一个补丁长度的键值对,作为参数传递给一个函数
        def greet_me(**kwargs):
            
            for key, value in kwargs.items():
                print('key = {0},value = {1}'.format(key, value))
                
                
            greet_me(小明=18, 小李=20)
        打印结果: 
    #   使用*args和**kwargs来调用函数
def test_args_kwargs(arg1, sex, age):
        print ("年龄:",arg1)
        print("性别:", sex)
        print ("年龄:",age)
args = ('小李','男',18)
# 下面两端注释的原因是 .items()  迭代方法 不可行  元组不能迭代 list 也不能迭代
# for k ,y,e in list(args).items():
#     print(k,y,e)
test_args_kwargs(*args)
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值