python基础知识之装饰器

类方法与静态方法

区别:类方法的第一个参数(例如cls)会自动绑定到类本身;静态方法不会绑定。
在类中,由@classmethod修饰的方法就是类方法;使用@staticmethod修饰的方法就是静态方法。

代码示例

class Dog(object):
	# @classmethod类方法
	@classmethod
	def run(cls):
		print("类方法run: ", cls)
	# @staticmethod静态方法
	@staticmethod
	def info(message):
		print("静态方法info:", message)
# 调用类方法,Dog类会自动绑定到第一个参数
Dog.run()
# 调用静态方法,不会绑定第一个形参,必须手动绑定
Dog.info("LOVE")
# 创建Dog对象
b = Dog()
# 使用对象调用run()类方法,其实依然还是使用类调用的
# 因此第一个参数依然被自动绑定到Dog类
b.run()
# 使用对象调用info()静态方法,其实依然还是使用类调用的
# 因此程序必须为第一个参数执行绑定
b.info('message')

总结

  1. 使用@classmethod修饰的方法就是类方法,无论程序是使用类还是类的实例调用该方法,Python始终都会将类方法的第一个参数绑定到类本身。
  2. 使用@staticmethod修饰的方法就是静态方法,无论程序是使用类还是类的实例调用该方法,Python都不会将类方法的第一个参数绑定到类本身。

@函数装饰器

@classmethod和@staticmethod的本质就是函数装饰器,其中classmethod和staticmethod都是Python内置的函数。
当程序使用@函数(比如函数A)装饰另一个函数(比如函数B)时,实际完成如下两部:
(1)将被修饰的函数(函数B)作为参数传给@符号引用的函数(函数A)
(2)将函数B替换(装饰)成(1)的返回值

代码示例

def functionA(fn):
	print("A")
	fn()  # 执行传入的fn参数
	return “functionA"
"""
下面的装饰效果相当于functionA(functionB)
functionB将会被替换(装饰)成该语句的返回值
由于functionA函数返回”functionA“,因此functionB就是”functionA“
"""
@functionA
def functionB():
	print("B")
print(functionB)  # functionA

总结

上面的程序使用@functionA修饰functionB,这意味着程序要完成两步操作。
(1)将functionB作为functionA()的参数,也就是上面的粗体字代码相当于执行functionA(functionB)
(2)将functionB替换为(1)执行的结果,functionA()执行完成后返回"functionA",因此functionB不再是函数,而是被替换成一个字符串。
运行上面程序,可以看到如下输出结果:
A
B
functionA

函数装饰器有什么用?
被修饰的函数总是被替换成@符号所引用的函数的返回值,因此被修饰的函数会变成什么,完全由@符号所引用的函数的返回值决定—如果@符号所引用的函数的返回值是函数,那么被修饰的函数在替换之后还是函数。

代码示例:

def foo(fn):
	# 定义嵌套函数
	def bar(*args):
		print("===1===", args)
		n = args[0]
		print("===2===", n*(n-1))
		# 查看传给foo函数的fn函数
		print(fn.__name__)
		fn(n*(n-1))
		print("*"*15)
		return fn(n*(n-1))
	return bar
"""
下面的装饰效果相当于foo(my_test)
my_test将会被替换(装饰)为该语句的返回值
由于foo()函数返回bar函数,因此my_test就是bar
"""
@foo
def my_test(a):
	print("==my_test函数==", a)
# 打印my_test函数,将看到实际上是bar函数
print(my_test)  # <function foo.<locals> .bar at 0x000000000021FABFA8>
# 下面代码看上去是调用my_test(),其实是调用bar()函数
my_test(10)
my_test(6, 5)

"""
上面程序定义了一个装饰器函数foo,该函数执行完成后并不是返回普通值,而是返回bar函数(这是关键),这意味着被该@foo修饰的函数最终都会被替换成bar函数。
上面程序使用@foo修饰my_test()函数,因此程序同样会执行foo(my_test),并将my_test替换成foo()函数的返回值,这说明my_test已经被替换成bar函数。接下来程序两次调用my_test()函数,实际上就是调用bar()函数。
运行上面程,可以看到如下结果:
<function foo.<locals> .bar at 0x000000000021FABFA8>
===1=== (10,)
===2=== 90
my_test
==my_test函数== 90
***********************
==my_test 函数==90
===1=== (6, 5)
===2=== 30
my_test
===my_test函数=== 30
**************
==my_test函数== 30
"""

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值