python学习之闭包和装饰器(入门)

闭包:

闭包 :一个函数里面嵌套一个函数,调用外层函数返回里层函数本身

示例1:

def fx(x):
    x +=1
    def fy(y):
        return  x*y
    return fy     # 不要加括号
f = fx(5)   # fy
n = f(5)   #fy()
print(n)  #30

示例2(入参是一个函数):

def f1(f2):
    print("f1执行")
    def f3(b):
        print("f3执行",f2(b)+1)
    return f3

def f2(a):
    return a+a
f=f1(f2)# f3
f(4)# f3()
#可以直接f=f1(f2)(4)
执行结果:
f1执行
f3执行 9

装饰器:

装饰函数的参数是被装饰的函数对象,返回原函数对象装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

示例1(还是刚才的f1,f2):

def f1(f2):
    print("f1执行")
    def f3(b):
        print("f3执行",f2(b)+1)
    return f3

@f1
def f2(a):
    return a+a    
f2(4)#9
#本来f2是计算一个数的平方,现在加了一个@f1修饰就成一个数的平方+1了。

在f2上加一个@f1,f1就是装饰器,而刚才演示的闭包的实现原理就是装饰器实现的原理。也可以说装饰器也是闭包。

还有一个更好诠释装饰器的例子:

#计算一个函数运行的时间:
import time
def countTime(fun):
    def count(*args,**kwargs):
        t1=time.time()
        print("开始时间:",t1)
        back=fun(*args,**kwargs)
        t2=time.time()
        print("结束时间:",t2)
        print("总用时:",t2-t1)
        return back
    return count

@countTime
def f(a):
    for i in range(a):
        print(i)

f(1000)
#输出结果:
'''
开始时间: 1517415914.1400516
1
2
...
999
结束时间: 1517415914.144096
总用时: 0.004044294357299805
'''

类装饰器

把一个类装饰到一个函数上。

示例:

class Tset_Class():
    def __init__(self,func):
        print('正在实例化')
        self.func = func
    def __call__(self, *args, **kwargs):   # 一定要写这个call
        print('这是call方法')
        return self.func

@Tset_Class
def  test():
    print('这是一个测试函数')

n =  test()   #    self.func : test 函数体
n() #这是一个测试函数

类装饰器的执行过程:

#  1.  @Tset_ClassTset_Class( test )  -> 相当于:t = Tset_Class( test )
#  2.  test()  ->  相当于:  t()  调用实例的call方法 -> 返回 self.func函数体
#  3.  n =  test()n()  调用test()

通过2.知道必须要写call方法

三个常用的装饰器

@property
装饰过的函数返回的不再是一个函数,而是一个property对象
装饰过后的方法不再是可调用的对象,可以看做数据属性直接访问。

示例:

class Test():
    def __init__(self,name):
        self.__name = name

    @property  # 把方法变成属性
    def get_name(self):
        return  self.__name

    @get_name.setter   # 可以让get方法,变成set方法
    def get_name(self,name):
        self.__name = name

    @property  # 把方法变成属性
    def po(self):
        print('asdfasdfasdfasdaf')

t = Test('xfy')        
print(t.get_name)#xfy
t.get_name = "stefan" #stefan
print(t.get_name)
t.po#123

Test类里有一个私有属性__name,这样在外界是不能访问的,曾经我们通过写一个get_name方法来获得__name的值,但是每次调用都是t.get_name(),现在加了@property,让这个方法变成像一个属性一样访问。

再加一个这样的@get_name.setter,就具备了赋值的能力。

@staticmethod #(静态方法)

@classmethod (类方法)

这两个装饰器详情请见Python学习之面向对象(封装、继承、多态)

对于装饰器的学习本篇只是初步,它的用途很大,主要作用就是权限控制,插入日志,性能测试,事务处理,缓存等。
还得等实际项目中碰到了,再深入学习。

有任何疑问,请留言评论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐同学呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值