python装饰器是什么?如何使用

一些后续会用到的名词解释

闭包 :定义在一个函数里面的函数,可以访问到外部函数的变量
eg:
inner_function就是一个闭包

def outer_function(x):
    def inner_function(y):
        return x + y
    return inner_function

add_five = outer_function(5)
result = add_five(3)  # 输出: 8

概念

装饰器实质是一个函数,它接受一个函数作为输入,并返回一个新的函数作为输出。(这句话要记住,编写装饰器要以这句话为准则)
------so允许我们在不修改原始函数代码的情况下,动态地添加额外的功能
------其实就是装饰器代码就是闭包加上一个语法糖@wraps

为什么要有装饰器

它可以实现对代码的重复利用,是一种代码优化方式

如何自定义装饰器

如何代码出来一个装饰器呢__
模版 :只需要修改 ‘添加一些操作 xx’ 这里的代码

def 函数名字(func):
  	def wrapper(*args, **kwargs):  # 一般这个闭包名字都叫wapper
        # 添加一些操作 xx
        result = func(*args, **kwargs)  # 调用原方法
        #添加一些操作 xx
        return result  # 返回结果
    return wrapper  #将闭包名字返回

怎么调呢?
@装饰器名字
func()

一个装饰器例子
场景:在每一个函数执行的时候打印出来函数的执行时间

import time
from functools import wraps           # 导入包

# !是不是符合接受一个函数为输入,并返回一个新的函数作为输出 ha
def timefunc(fun):
    @wraps(fun)                       # 固定语法糖 保存传入函数的元数据!不然func数据丢啦!
    def wrapper(*args, **kwargs):     # 固定写法
        start = time.time()
        result = fun(*args, **kwargs) # 固定写法 *args, **kwargs接收任何参数
        end = time.time()
        print('run time', end-start)
        return result
    return wrapper					

@timefunc							# 固定写法
def func():
    print('heihei, i am func')

func() # 其实就是执行了wrapper函数,wrapper里面由执行了原本的func函数,并返回了func执行结果

运行结果
heihei, i am func
run time 1.1205673217773438e-05

系统中有哪些常用内置的装饰器

@property

把类方法变为一个属性来使用,可以去做一些对这个属性的额外的操作,调用时候比较干净简洁
如何使用?
一个类的方法+@peoperty属性后,就可以这个属性的setter getter delete 方法,setter getter delete中可以去做一些额外的操作 看eg理解吧
例子eg
获取和设置名字,希望在设置名字的时候,做一下参数类型检查

class A:
    def __init__(self, name):
        self.obj_name = name
    @property
    def obj_name(self):
        return self._obj_name

    @obj_name.setter
    def obj_name(self, name): 
        print('set name ')
        if not isinstance(name, str):
            raise TypeError('Excepted type')
        self._obj_name = name

    @obj_name.getter
    def obj_name(self):
        print('get name ')
        return self._obj_name


a = A('lisa')
a.obj_name= 'nana'
a.obj_name

输出
set name 
set name 
get name 

解析一下这个例子吧
a = A(‘lisa’) 后会运行到self.obj_name = name ,所以才会调用到被@obj_name.setter修饰的方法
a.obj_name= ‘nana’ 这是个设置属性操作,会调用到被@obj_name.setter修饰的方法
a.obj_name 明显是一个get类型的方法哈 所以调用到@obj_name.getter修饰的方法

@staticmethod

静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系
特性:静态方法中,不会涉及到类/对象中的属性和方法的操作!
so:静态方法就是存在类中,但是它就是它,只是占用类的存储空间罢了,谁也别挨lz。(这该死的表达欲)
例子

import time

class TimeTest(object):
    def __init__(self, hour, minute, second):
        self.hour = hour
        self.minute = minute
        self.second = second

    @staticmethod
    def showTime():						# 任何属性/方法都不调用!
        return time.strftime("%H:%M:%S", time.localtime()) 


print(TimeTest.showTime())
t = TimeTest(2, 10, 10)
nowTime = t.showTime()
print(nowTime)

@classmethod

适用于在方法内部,需要对类本身的一些属性操作的场合。不是独属于哪个类对象的操作
例子:
比如对学生的数量统计 (__num是属于类ClassTest的属性,addnum和getnum对其操作)

class ClassTest(object):
    __num = 0

    @classmethod
    def addNum(cls):
        cls.__num += 1

    @classmethod
    def getNum(cls):
        return cls.__num

    # 这里我用到魔术方法__new__,主要是为了在创建实例的时候调用累加方法。
    def __new__(self):
        ClassTest.addNum()
        return super(ClassTest, self).__new__(self)


class Student(ClassTest):
    def __init__(self):
        self.name = 'xx'

a = Student()
b = Student()
print(ClassTest.getNum())

输出 2
思考一下?如果不在getNum上方+@classmethod会不会报错?
会 : TypeError: addNum() missing 1 required positional argument: 'cls'

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值