缺省参数和装饰器

对缺省参数的理解

缺省参数和关键字参数对应:缺省参数是形参,关键字参数是实参。
调用函数的时候,如果没有传入该缺省参数的值,就取缺省参数的默认值,直白地说,就是你传,就用你的;你不传,我就用默认的。

def info(name,age=18):
    # age = 18 就是缺省参数
    print("name is %s" %name)
    print("age is %d" %age)

# 调用函数
info(name='jack') # 未给age传参数,就去默认值age=18
# 输出结果:name is jack age is 18

# 调用函数
info(name='jack',age=66) # 传给关键字参数 则age=66
# 输出结果:name is jack age is 66
装饰器的理解

作用:写代码需要遵循开放封闭原则,它规定已经实现的功能代码不允许被修改,但是可以被扩展。
当我们需要为一段已经写好的代码添加功能的时候,在不改变源代码的情况下,加一个装饰器完成功能的添加功能。
例如:
(1)引入日志
(2)函数执行时间统计
(3)执行函数之前的预备处理
(4)执行函数之后的清理功能
(5)权限校验等场景
(6)缓存

装饰器实现原理

1、先了解闭包

# 定义一个函数
    def test(number):
        # 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量
        # 那么将这个函数以及用到的一些变量称之为闭包
        def test_in(number_in):
            print("in test_in函数,number_in is %d" %number_in)
            return number + number_in
        # 其实这里返回的就是闭包的结果
        return test_in


    demo = test(3)
    print(demo(2))
  1. @函数名(python的语法糖)@test下面的函数作为test函数的参数

    def test1(func):
        def wrapped1():
            # 验证1
            return func() + '<xiexie>'
        # 这里不带()返回的是闭包的结果
        return wrapped1
    
    def test2(func):
        def wrapped2():
            # 验证2
            return func() + '<nihao>'
        # 这里不带(),返回的是闭包的结果
        return wrapped2
    
    @test1
    @test2
    def info():
        return 'hello'
    
    print(info())
    # 返回结果
    # hello<nihao><xiexie>
    
装饰器原理分析

装饰阶段:将装饰器装饰的函数当做参数,传给装饰器,返回一个闭包(这里用到了闭包,外部的参数会传递给内部函数的引用,而不会被释放),并且赋值给原函数名,使原函数名指向了这个闭包。而此时装饰器的参数func指向原来的函数;
执行阶段: 调用原函数实际是调用的闭包,闭包在指向原函数前可以执行一段我们要加的逻辑。
装饰器开始装饰不是随着执行函数时装饰,而是在创建在对这个函数装饰时就装饰。
每装饰一个就创建一个闭包。

装饰问题,变量名指向问题

    @test2
    def info():
    此时原函数名info指向@test2装饰创建的闭包---wrapped2
    test2(func)的参数func,指向原来的函数info。

    @test1
    ...
    此时原函数名info指向@test1装饰创建的闭包---wrapped1;
    test1(func)的参数func,指向@test2装饰
    test2(func)的参数func,指向原来的函数info
装饰器参数(也可以是不定长参数)
    from time import ctime,sleep

    # 这个装饰器的作用是在函数开始之前打印开始时间
    def timefun(func):
        def wrapped_func(a,b):
            print("%s called at %s" %(func.__name__,ctime()))
            print(a,b)
            func(a,b)
        return wrapped_func

    @timefun
    def foo(a,b):
        print(a+b)

    foo(3,5)
    sleep(2)
    foo(2,4)

    # 运行结果
    # foo called at Tue Apr 10 15:50:30 2018
    # 3 5
    # 8
    # foo called at Tue Apr 10 15:50:32 2018
    # 2 4
    # 6
类装饰器(扩展)

类装饰器其实是一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但是也有例外。只要某个对象重写了call () 方法,那么对象就是callable的。

    # 类装饰器demo

    class Test(object):
        def __init__(self,func):
            print("---初始化---")
            print("func name is %s" %func.__name__)
            self.__func = func
        def __call__(self):
            print("---装饰器的功能---")
            self.__func()


    # 说明:
    # 1. 当使用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
    # 并且会把test这个函数名当作参数传递到__init__方法中
    # 即在__init__ 方法中的属性__func指向了test指向的函数
    # 
    # 2. test指向了用Test创建出来的实例对象
    # 
    # 3. 当在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的__call__方法
    # 4. 为了能够在__call__方法中调用原来test指向的函数体,所以在__init__方法中就需要
    # 一个实例属性来保存这个函数体的引用
    # 所以才有了self.__func = func 这句代码,从而在调用__call__方法中能够调用到
    # test之前的函数体

    @Test
    def test():
        print("---test---")

    test()
    showpy()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值