在解释@函数装饰器之前,先说一下,类中的类方法和静态方法。
在Python中完全支持定义类方法、静态方法。这两种方法很相似,Python它们都使用类来调用(ps:用对象调用也可以)。
区别在于:Python会自动绑定类方法的第一个参数,类方法的第一个参数会自动绑定到类本身;但对于静态方法则不会自动绑定。
类方法用@classmethod修饰,静态方法用@staticmethod修饰,如下:
1 #coding=utf-8
2 class Person:
3 @classmethod
4 def eat(cls):
5 print("类方法eat:",cls)
6
7 @staticmethod
8 def sleep(p):
9 print("静态方法sleep:",p)
10
11
12 Person.eat()
13 Person.sleep("info")
14
15 p = Person()
16
17 p.eat()
18 p.sleep('info')
控制台打印如下:
解释:eat方法因为是@classmethod修饰所以它是类方法,所以第12行调用时,不用传入任何参数,即可以调用,因为它会自动绑定类本身到第一个参数。
sleep方法因为是@staticmethod修饰所以它是静态方法,所以在第13行调用时,需要传入参数。再看17、18行,可以得出结论:不管是用类或者对象调用静态方法,Python都不会对静态方法的第一个参数进行自动绑定。
上面的@classmethod 和 @staticmethod 其实就是函数装饰器,其中classmethod和staticmethod为Python中内置的函数。
使用@符号引用已有函数后,可用于修饰其他函数。
例如@函数A 装饰 函数B ,实际完成的步骤为:
1.将被装饰的函数B作为参数传给函数A
2.将函数B替换为第1步的返回值。
举个例子:
1 def funA(fn):
2 """参数为一个函数对象"""
3 print('A')
4 fn() #执行传入的fn函数
5 return 'tizer'
6
7 '''
8 下面的代码相当于funA(funB)
9 funB将会被替换为该语句的返回值
10 由于funA返回tizer,因此funB就是tizer
11 '''
12 @funA
13 def funB():
14 print('B')
15 print(funB)
先看运行结果:
解释:既然funB作为参数传给了funA,那就是得先执行funA中的代码,所以执行了print(‘A’),打印了A,然后执行第4行fn(),因为传入的funB,funB中的代码为print('B'),所以打印了B,然后funA 返回了一个字符串tizer,所以funB 等同于 tizer,第15行print(funB) 等同于 print('tizer'),所以打印了tizer。