类的内置方法
它与内置函数有紧密的联系,有的内置函数就是调用的内置方法。
在顶级父类obj中有:
两个双下方法
obj.__str__ str(obj)
obj.__repr__ repr(obj)
1、__str__ 与 __repr__
1 class Teacher: 2 def __init__(self, name, salary): 3 self.name = name 4 self.salary = salary 5 6 def __str__(self): 7 return "Teacher's object :%s" % self.name 8 9 def __repr__(self): 10 return str(self.__dict__) 11 12 def func(self): 13 return 'wahaha' 14 15 16 nezha = Teacher('哪吒', 250) 17 print(nezha) # 打印一个对象的时候,就是调用a.__str__ 18 print(repr(nezha)) 19 print('>>> %r' % nezha)
a.__str__ --> object
object 里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址
l = [1,2,3,4,5] # 实例化 实例化了一个列表类的对象
print(l)
%s str() 直接打印 实际上都是走的__str__
%r repr() 实际上都是走的__repr__
repr 是str的备胎,但str不能做repr的备胎
print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串
如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
repr(),只会找__repr__,如果没有找父类的
内置的方法有很多,但是不一定全都在object中

1 class Classes: 2 def __init__(self, name): 3 self.name = name 4 self.student = [ ] 5 6 def __len__(self): 7 return len(self.student) # obj中没有该方法,因为obj只存所有对象共有的! 8 9 def __str__(self): 10 return 'classes' 11 12 13 py_s9 = Classes('九年级三班') 14 py_s9.student.append('董青') 15 py_s9.student.append('久美') 16 print(len(py_s9)) 17 print(py_s9) 18 19 # 1、__str__ 20 print(str(12)) # 其实就是调用int类型的__str__方法 21 22 23 # 为了验证,可以来一个例子: 24 class StrDemo: 25 def __init__(self, name): 26 self.name = name 27 28 # def __str__(self): 29 # print('调用我的str双下方法了!') 30 # return self.name 31 def __repr__(self): 32 print('调用我的repr双下方法了!') 33 return self.name 34 35 36 s = StrDemo("string") 37 print(str(s)) 38 39 # 2、__repr__ 40 print(repr('1')) 41 print(repr(1)) 42 # 我们将StrDemo类中的__str__方法注释掉,看看发生什么? 43 print(repr(s)) 44 45 46 # 当一个类没有重写__str__方法,但是重写了__repr__方法,当使用str(本类实例)的时候,就调用了__repr__ 47 # 即__repr__是__str__的备胎,但是反过来就不行!
2、析构函数(__del__)
功能是在回收内存中的对象,并在回收前做一些收尾工作,如打开的文件没关闭,将其关闭等!

1 class A: 2 def __init__(self, f): 3 self.f = f 4 5 def __del__(self): 6 print('it deling') 7 self.f.close() # 析构函数: 在删除一个对象之前进行一些收尾工作 8 9 10 a = A(open('2_反射进阶.py')) 11 del a # del 既执行了这个方法,又删除了变量 12 13 14 # del a NameError: name 'a' is not defined 15 16 # 引用计数中用到该内置方法
3、item相关方法:__getitem__ __setitem__ __delitem__

1 class Person: 2 def __init__(self, name,age,ginder): 3 self.name = name 4 self.age = age 5 self.ginder = ginder 6 7 def __getitem__(self, item): 8 if hasattr(self, item): 9 return self.__dict__[item] 10 11 def __setitem__(self, key, value): 12 self.__dict__[key] = value 13 14 def __delitem__(self, key): 15 print('it is calling me !') 16 self.__dict__.pop(key) 17 18 tom = Person('tom', 22, 'male') 19 # 得到属性 20 print(tom['ginder']) # __getitem__可以用访问字典中的元素一样访问对象的属性! 21 # 设置属性 22 tom['kind'] = 'superman' 23 print(tom.kind, tom['kind']) 24 #del tom.kind # object 原生支持 __delattr__ 25 del tom['kind'] # 通过自己实现的 26 print(tom.kind, tom['kind'])
4、__hash__ 对应 hash()内置函数
查看hash值,可以修改hash规则,是的本来有不同hash值的两个对象有一样的hash值

1 lass Hash: 2 def __init__(self, name): 3 self.name = name 4 5 def __hash__(self): 6 return hash(self.name) 7 8 9 ha_a = Hash('a_Hash') 10 hah = Hash('a_Hash') 11 print(hash(ha_a), hash(hah)) # 两个对象虽然名字一样,但是hash值不同:-9223371888545262739 148309513073 12 # 实现object中的__hash__方法,并只返回name的hash值,就相等了:-9184190014575666570 -9184190014575666570
5、__new__ 构造函数,在初始化函数前,将self构造出来。
典型使用:单例模式(23种设计模式第一个)
即:一个类在内存中,始终只有一个实例
__init__ 初始化方法
__new__ 构造方法 : 创建一个对象

1 class Singleton(): 2 __instance = False 3 def __init__(self, name): 4 self.name = name 5 6 def __new__(cls, *args, **kwargs): 7 '''实现单例''' 8 if cls.__instance: 9 return cls.__instance 10 else: 11 cls.__instance = object.__new__(cls) 12 return cls.__instance 13 14 a = Singleton('a') 15 a.nm = '单例' 16 b = Singleton('b') 17 print(b.nm) 18 print(id(a), id(b)) # 没有实现__new__方法前的结果是:2681905465888 2681905467232 地址不同,说明是两个对象 19 # __实现__new__方法后,即使不写具体操作,直接pass,也返回相同的地址:1760945392 1760945392 20 # 实现单例的操作后,地址变为:2491487242000 2491487242000 还是相同,即为同一对象!
6、 __eq__方法

1 class Equal: 2 def __init__(self, name): 3 self.name = name 4 5 def __eq__(self, other): 6 if self.name == other.name: 7 return True 8 9 double_eq = Equal('双等于号') 10 eq = Equal('双等于号') 11 # 问:两个对象相等吗? 12 print(double_eq, eq, double_eq == eq) 13 # <__main__.Equal object at 0x0000027726CA3828> <__main__.Equal object at 0x0000027726CA3860> False 14 # 内存地址不一样,是两个对象,所以不等,双下eq方法,是继承自顶级的object类,原来就是比较内存地址的! 15 # 实现该方法的其他类,如str,int等,改为值等就是相等了! 16 # 如何让两个相同的名字的Equal对象,变为相等了?只有重写eq方法了 17 print(double_eq == eq)
7、__call__ 方法
1 class B: 2 def __init__(self, name): 3 self.name = name 4 5 def __call__(self): 6 for k in self.__dict__: 7 print(k, self.__dict__[ k ]) 8 9 10 B('sb')() # 最后一个()就是在调用该类中的双下call方法!