一些后续会用到的名词解释
闭包 :定义在一个函数里面的函数,可以访问到外部函数的变量
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'