函数修饰符
函数修饰符的作用是为现有函数增加额外的功能,比如日志插入、性能测试等。
创建函数修饰符的规则有以下四点:
- 修饰符是一个函数;
- 被修饰函数是修饰符的参数;
- 修饰符返回一个新函数;
- 修饰符维护被维护函数的签名(原函数还是按照以前的标识符调用,但功能多了一些);
被修饰函数不带参数
我们有一个函数用于计算1到10000的整数和:
def sum():
total = 0
for i in range(1,10001):
total += i
print(total)
我们希望能得到这个函数的运行时间,但是又不希望对函数sum进行修改,于是,我们运用修饰符。
import time
def calculate_time(func):
def wrapper():
t1 = time.time()
func()
t2 = time.time()
spend = t2 - t1
print(f'花费的时间是{spend}s')
return wrapper
@calculate_time
def sum():
total = 0
for i in range(1,10001):
total += i
print(total)
if __name__ == '__main__':
sum()
输出的结果是:
50005000
花费的时间是0.0006659030914306641s
wrapper才是最终起到作用的函数,也就是说,修饰函数内部的一切,是sum需要执行的。
修饰函数的参数是函数。
我们查看sum函数的name,发现其实际上正式wrapper
print(sum.__name__)
输出的结果是:
wrapper
被修饰函数带参数
另外,被修饰函数还有返回值。
import time
def calculate_time(func):
def wrapper(*args,**kwargs):
t1 = time.time()
ret = func(*args,**kwargs)
t2 = time.time()
spend = t2 - t1
print(f'花费的时间是{spend}s')
return ret
return wrapper
@calculate_time
def sum(start,end):
total = 0
if end > start :
for i in range(start,end+1):
total += i
print(total)
return total
if __name__ == '__main__':
total = sum(1,10000)
改动有两点:
- wrapper函数和func函数都加上了参数;
- wrapper函数给予了return。
实验表明,参数改为(start,end)也可以,但比较有针对性。
类修饰符
@classmethod
class A(object):
bar = 1
def __init__(self,name):
self.name = name
@classmethod
def printf(cls): # cls参数是默认传递进去的
print(cls.bar)
if __name__ == "__main__":
A.printf()
被修饰的函数不需要类实例化,也不需要self参数,但第一个参数需要是表示自身类的cls参数。
@property
class A(object):
def __init__(self,name):
self.name = name
@property
def print():
print('100')
if __name__ == "__main__":
A.print
被修饰对象不需要加括号就可以直接调用。
@classmethod和@staticmethod的区别
有关类的方法分为三种,分别是:
- 静态方法(staticmethod)
- 类方法(classmethod)
- 实例方法
带有self的,就是实例方法,需要将类实例化之后,才可以调用一个函数。
区别:
- staticmethod不需要表示自身对象的self和自身类的cls参数,和使用函数一样;classmethod不需要self参数 但是需要cls参数。
- 如果在staticmethod中调用这个类的一些属性方法,只能直接 类名.属性名或类名.方法名;而classmethod之因为持有cls参数,可以直接调用类的属性、类的方法。