8.5 打印对象

打印的时候,print函数能直接打印内置的各种变量和对象,例如打印一个整数、一串字符,或者一个列表:
a=3
print(a)
b='good'
print(b)
c=[1,12,45,6,4]
print(c)
但是直接打印自定义类的对象的时候,print函数就无能为力了,因为对象有若干个属性,打印到底要如何打印呢?看下面的例子:
class Student:
    name=""
    id=""
    clazz=""
    
s=Student()
s.name="乔峰"
print(s)  # 这句会打印出类似这样的: __main__.Student object at 0x7f1198ee7fd0
第8行代码直接打印了Student对象s,理论上这种对象有三个属性,直接打印s,print函数并不会自行组织如何打印这些函数。python的类提供了一个直接打印对象的机制,只需要在函数里定义__str__函数(前后都是两个下划线),
class Student:
    name=""
    id=""
    clazz=""
    def __str__(self):
        return "姓名:"+self.name+",学号:"+self.id+",班级:"+self.clazz
s=Student()
s.name="乔峰"
s.id="A2010456342"
s.clazz="一品堂"
print(s)  # 这句会打印出类似这样的:姓名:乔峰,学号:A2010456342,班级:一品堂
也就是说如果类定义了__str__函数,那么直接用print打印这种类的对象的时候,实际上打印的是__str__函数返回的字符串。
__str__函数和构造函数一样,是类内部特殊的函数,它要遵循的规则是:
1.函数必须返回字符串
2.函数前后都是两个下划线,函数的参数必须是self

也可以直接调用此函数,把一个对象转化成一个字符串:
class Student:
    name=""
    id=""
    clazz=""
    def __str__(self):
        return "姓名:"+self.name+",学号:"+self.id+",班级:"+self.clazz
s=Student()
s.name="乔峰"
s.id="A2010456342"
s.clazz="一品堂"
p=s.__str__() #先调用__str__生成字符串,再打印
print(p) # 这句会打印出类似这样的:姓名:乔峰,学号:A2010456342,班级:一品堂

除了__init__和__str__,Python类中还有许多其他特殊方法(也称为魔术方法或双下划线方法),它们可以定制类的行为。以下是一些常用的特殊方法:
__eq__(self, other): 定义相等性运算符,当两个对象(self和other)相等时(两个对象如何相等,由类的设计者决定)返回True。也就是两个对象可以使用a==b。
__lt__(self, other): 定义小于运算符,用于排序及两个对象(self和other)的比较操作。也就是两个对象可以使用ab。    
__le__(self, other): 定义小于等于运算符,用于排序及两个对象(self和other)的比较操作。也就是两个对象可以使用a<=b。    
__ge__(self, other): 定义大于等于运算符,用于排序及两个对象(self和other)的比较操作。也就是两个对象可以使用a>=b。
class Student:
    name = ""
    id = ""
    clazz = ""
    def __str__(self):
        return "姓名:" + self.name + ",学号:" + self.id + ",班级:" + self.clazz
    def __eq__(self, other):
        print("eq函数被调用")
        if self.id == other.id:
            return True
        else:
            return False
s = Student()
s.name = "乔峰"
s.id = "A2010456342"
s.clazz = "一品堂"
t = Student()
t.name = "乔峰"
t.id = "A2010456342"
t.clazz = "大理"
if s == t:  # 此时会触发__eq__函数,可看到"eq函数被调用"被打印
    print(True)

   
   __hash__(self): 返回一个哈希值,用于将对象作为字典键。
   __len__(self): 返回对象的长度,通常用于序列类型的类。也就是对象可以使用len(a)来计算其长度,对象的长度通常由其属下决定。
   __getitem__(self, key): 返回与指定键相关联的值。
   __setitem__(self, key, value): 设置与指定键相关联的值。
   __delitem__(self, key): 删除与指定键相关联的值。
__repr__(self): 返回一个字符串,用于表示对象的"形式",通常在调试及开发过程中使用。
__new__(cls[, ...]): 用于创建对象实例,通常在重写不可变类型时使用。在对象产生之前调用,而init方法在对象产生之后才调用。

这些特殊方法中的大多数都可以用于自定义类以实现需要的行为。