class wow():
def __init__(s,x):
s.x = x
def __add__(s,y):
return wow(s.x+y.x)
def __sub__(s,y):
return wow(s.x-y.x)
def __repr__(s):
return str(s.x)
a=wow(5)
b=wow(7)
c=wow(3)
res=a-b+c
print(res)
在一个类中对特殊操作符的进行重新定义之后,这个类的实例关于这个操作符的运算就可以根据类中定义的方法进行操作。这种对操作符的重新定义也被称为操作符的重载。
在python中,以双下划线开始和结束的函数定义(比如说__self__
),就是对操作符或者函数的重载。上面的Python代码可以实现a,b,c之间的加减法运算,代码中的wow类对操作符“-,+,()”进行了重定义。之后关于wow的实例a,b,c中“-,+,repr函数”之间的运算就会以wow类中的方法进行操作。
以加法为例,在不对操作符进行重载的情况下,程序是不能实现两个wow实例的直接相加的。对“+”进行了重定义后,这时,在对wow实例进行“+”操作相当于对实例中的两个数据进行加法运算,最后,在将wow输出的数据以wow实例的形式输出(return wow(s.x+y.x)
)。这里,在一个类的定义里,实现了对两个实例的操作。
str可以将结果以字符串的形式显示(如果本身数据就是字符串,那么就只需要按数据原来的样子输出就可以了);repr即使不被print调用,当需要显示时也会把数据进行字符串转换。除了可以具有str的作用之外,repr还可以将不能转化成字符串的数据的内存读出来。在使用print函数时,首先会调用str函数,如果print所处理的类没有定义str,print就会尝试调用repr。如果连repr都没有,print输出的东西就不知道输出的是什么了。可以通过下面两个例子区分str,repr。
class wow(object):
def __init__(s,a):
s.x = a
def __str__(s):
return str(s.x)
a=wow(5)
在shell中输入上面的python程序,然后直接输a,结果显示
“<main.wow object at 0x7fa93c00e2e8>”;
如果在shell中输入print(a),结果就显示整数5。
如果把上面python程序的str
改成repr
,即
def __repr__(s):
return repr(s.x)
此时无论直接输入a,或者输入print(a),结果都是整数5。
所以,从上面的例子可以看出:
1,如果类中只有对str的重定义,如果将a直接输出,并不会调用到wow中的__str__
。
2,如果类中只对repr进行重定义,不管是直接输出a,或是print(a)(因为没有__str__
,所以print会调用__repr__
),都可以调用到__repr__
,实现字符串的转换。(根据这一点,python reference讲repr函数可以用于调试,如何是这样的,我现在还不能明白。关于repr的重定义)
3,在开始的程序中,代码对repr进行重定义,使repr调用str函数。由于repr可以显示数据时调用,然后在对数据进行str操作。所以如果在命令行中输入a,也会显示整数5。