python中@符的用法

python中目前@有两种用法,一个是用于装饰器,一个是用于矩阵乘法的重载符

# 用法一:语法糖
# 在python2.x和<=3.4版本中,@只用作装饰器,用法如下:

@a_decorate_func	# 其实此处只要是一个可以使用()调用语法的标识符即可
def fun(*args, **kargs):
	pass
	
# 上面的代码与下面的代码效果是一样的,为了我们写代码方便,才提供了上面的语法
# 我猜测可能不止效果一样,最终的代码都是一样的,解释器会先将上面的代码直接变成下面的代码

def fun(*args, **kargs):
	pass
fun = a_decorate_func(fun)

# 也就是说用于装饰器的@符,其实只是一个简单的代码替换(我猜是编译器会将上面的@用法
# 直接替换成下面的代码,官方文档上也是说它们是等价的,但是没有具体说明原理)
# 我这样子猜测也是有原因的,因为我测试过,只要@后面跟一个能够使用()的标识符就可以,
# 比如是一个函数,或者是一个callable实例对象,或者是类名(该类不一定要实现__callable__())

# 它们三这有一个共同的特征,就是后面可以直接跟(),并且如果类A实现了__callable__(),
# 则@A()的写法也是可以的,此处就更明显了,解释器会先执行A(),返回以A的实例对象,然后就和
# @后面直接跟一个实例对象是一样的了,这就是说@A()的写法中,A()会先被执行,然后取得其结果
# 此时只有认为解释器确实是将@A()替换成fun=A()(fun)才比较合理,此时A()才会被先执行一下 

# 用法二:矩阵乘法
# 此用法只能是在>=python3.5中使用,python2中不能用

# 此用法其实就是操作符重载,解释器会把@运算转换成对__matmul__()方法的调用
# 所以要使用@作为矩阵乘法,则这个类必须实现__matmul__()方法噢
# 举个栗子
class A:
	def __init__(self, val):
		self.val = val
	def __matmul__(self, b):	# 定义与@符号绑定的函数
		print("in __matmul__ A", self.val, b.val)
	def __mul__(self, b):		# 定义与*符号绑定的函数
		print("in __mul__ A", self.val, b)
	def __rmul__(self, b):		# 定义右乘,即A类对像在*右侧,且*左侧不是A对象时调用
		print("in __rmul__ A", self.val, b) 
a = A(100)
b = A(200)
a@b 	#out: in __matmul__ A 100 200
a*b		#out: in __mul__ A 100 <__main__.A object at 0x7f8aca1f16d8>
a*10	#out: in __mul__ A 100 10
10*a	#out: in __rmul__ A 100 10

# 当然我上面只是为了验证@和*所绑定的方法是哪些,实际应用中还是要根据需要来定义这些方法的
# 比如@一般是用于矩阵乘法,实现__matmul__时,就要根据你的需求来实现矩阵乘法,而不是像我
# 上面写的那样,直接print一下了.

好啦,python中的@目前应该就只有这两种用法了,小伙伴儿们现在是不是清晰了呢?


装饰器部分的知识讲的比较少,不太理解也没关系的,只要记得有这么回事就好啦

你可能感兴趣的:(python,python,@,运算符重载)