魔术方法:“魔术方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一切都是自动发生的。”
写过java的人都知道,java中如果想要打印对象信息,有一个toString方法。类实现这个方法后,打印对象时,可以打印出对象的字段信息,如果类没有实现这个方法,打印出来的则是对象的内存地址,看不到对象的具体字段信息。
python也一样,看下面一个案例。
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
per = Person('peter', 18)
print(per)
输出:
<__main__.Person object at 0x000002740A26E518>
可以看到,如果直接打印对象,输出的是对象的内存地址信息,从这个信息里面获取不到对象实例的任何字段信息。为了解决这个问题,Python提供了两种魔术方法。
__str__方法
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "person: name = %s, age = %s"%(self.name, self.age)
per = Person('peter', 18)
# 先转换成str类型再输出
perstr = str(per)
print(perstr)
# 直接通过print输出
print(per)
输出:
person: name = peter, age = 18
person: name = peter, age = 18
__str__方法实际上就是让对象可以被转换成str类型,在执行str(per)时会自动调用__str__方法,前面__call__也是一个魔术方法,类实现__call__方法后创建的对象实例是可调用的。所以,z正如前言所说,魔术方法可以给类提供更多的特性。
__repr__方法
虽然__str__方法可以实现打印对象,但是使用上还是有局限,比如像在控台上通过对象是打印不出来的,其次如果list集合元素是对象,直接打印list集合也打印不出来对象信息。这个时候__repr__可以派上用处。
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return "person: name = %s, age = %s"%(self.name, self.age)
per = Person('peter', 18)
print(str(per))
pers = []
pers.append(per)
# 打印list集合
print(pers)
输出:
person: name = peter, age = 18
[person: name = peter, age = 18]
通过对比可以发现,__repr__方法比__str__更强大,但是更强大往往意味着更损耗性能,虽然说大多数时候没什么影响,但是养成一个好的编程习惯很重要,如果是仅仅只是打印对象实例,不需要直接输出list集合这种对象信息,推荐优先使用__str__方法。