python 装饰器和闭包函数

python装饰器和闭包函数

一、 内置装饰器

1、内置类装饰器

1)不用实例化、直接调用
2)提升代码的可读性

2、普通方法

1)定义:第一个参数为self,代表 实例本身
2)调用:要有实例化的过程,通过 实例对象.方法名 调用
# 1. 定义
class MethodsDemo:
    param_a = 0 #类变量
    def normal_demo(self): # 定义一个类方法,第一个参数必须为self
        """
        普通方法
        :return:
        """
        print("这是一个普通方法", self.param_a)
# 2. 调用
md = MethodsDemo()
md.normal_demo()

3、类方法

1)定义:
    * 使用 @classmethod 装饰器,第一个参数为类本身,所以通常使用cls命名做区分(非强制)
    * 在类内可以直接使用类方法或类变量,无法直接使用实例变量或方法
2)调用:
    * 无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
# 1. 类的定义
class MethodsDemo:
    param_a = 0
    # 定义类方法必须加 classmethod装饰器
    @classmethod
    def classmethod_demo(cls):
        """
        类方法,第一个参数需要改为cls
        :return:
        """
        print("类方法", cls.param_a)

# 2. 类的调用
MethodsDemo.classmethod_demo() # 无需实例化,直接调用

4、静态方法

1)定义:
    * 使用 @staticmethod 装饰器,没有和类本身有关的参数
    * 无法直接使用任何类变量、类方法或者实例方法、实例变量
2)调用:
    * 无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
# 1. 定义
class MethodsDemo:
    param_a = 0
    @staticmethod
    def static_demo():
        """
        静态方法
        :return:
        """
        print("静态方法") # 无法直接调用类变量
# 2. 调用
MethodsDemo.static_demo()

二、闭包函数和自定义装饰器

1、函数引用

1)函数可以被引用
2)函数可以被赋值给一个变量
def hello():
    print("school")

harry = hello
harry()

2、闭包函数

1)闭包的内部函数中,对外部作用域的变量进行引用
2)闭包无法修改外部函数的局部变量
3)闭包可以保存当前的运行环境
def output_student(grade):
    def inner(name, gender):
        print(f"学生的名称是{name},性别是{gender},年级是{grade}")
    return inner

student = output_student(1)
student("罗恩", "男")
student("哈利", "男")
student("赫敏", "女")

3、自定义装饰器

函数体开始执行与结束执行的时候分别添加打印信息
# 不使用装饰器的代码
def timer(func):
    print("计时开始")
    func()
    print("计时结束")

def ho01():
    print("python语言")

timer(ho01)

# 使用装饰器的代码
def timer(func):
    def inner():
        print("计时开始")
        func()
        print("计时结束")
    return inner

@timer
def ho():
    print("python语言")

ho()

4、练习

实现一个计时器的装饰器,计算函数执行时间
import datetime
def timer(func):
    # 如果被装饰函数有参数,则需要在内函数加形参以及在函数调用时,添加参数信息
    # 将两个地方的参数换为不定长参数,解决写死参数个数不一致问题
    def inner(*args, **kwargs):
        # 获取当前时间
        start_time = datetime.datetime.now()
        func(*args, **kwargs)
        end_time = datetime.datetime.now()
        print(f"函数的执行时间{end_time-start_time}")
    return inner

@timer
def hogwarts(name):
    print("霍格沃兹测试学社", name)