__len__
class A: def __init__(self,name): self.name=name def __len__(self): return len(self.name) liu=A("liulin") #实例化 print(len(liu)) #调用类中的__len__() 方法,如果类中没有__len__(),则报错
__eq__
等号比较,定制返回值:== 自动触发
class A: def __init__(self,name,cls,age,sex): self.name = name self.cls = cls self.age = age self.sex = sex lin = A('小','1班',18,'无') lin2 = A('小','1班',18,'无') print(lin==lin2) #返回False,因为比较的是内存地址,值一样,地址不一样

class A: def __init__(self,name,cls,age,sex): self.name = name self.cls = cls self.age = age self.sex = sex def __eq__(self, other): #在类中定义一个__eq__():方法,只要用==比较,一定执行此函数 if self.__dict__ == other.__dict__: #如果值相等 return True else: return False lin = A('小黑','py10期',18,'无') lin2 = A('小黑','py10期',18,'无') print(lin==lin2) #返回True

class A: def __init__(self,name,cls,age,sex): self.name = name self.cls = cls self.age = age self.sex = sex def __eq__(self, other): #在类中定义一个__eq__():方法,只要用==比较,一定执行此函数 return True #只要比较,一定返回True lin = A('小','1',18,'无') lin2 = A('大','2',19,'无') print(lin==lin2) #返回True
__format__
定制输出格式
format_dict={ 'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名 } class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type def __format__(self, format_spec): return format_spec.format(obj=self) s1=School('成栋','北京','私立') #实例化 三个属性 print(format(s1,format_dict['tna'])) #把对象和定制的格式传进去 print(format(s1,format_dict['nat'])) print(format(s1,format_dict['tan'])) '''输出: 私立:成栋:北京 成栋-北京-私立 私立/北京/成栋 '''
__str__
class Person: def __init__(self,name,age): self.name=name self.age=age liulin=Person('刘林',25) print(liulin) #直接打印对象 <__main__.Person object at 0x00000194EC747DA0> ---------------------------------------------------------------- #如果想返回属性 class Person: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return str(self.__dict__) #返回的必须是字符串,否则报错 liulin=Person('刘林',25) print(liulin) #直接打印对象就可以打印出结果:{'name': '刘林', 'age': 25}
print(str(liulin))
print("%s"%liulin) 三个结果一样
__repr__
class Person: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return str(self.__dict__) #返回的必须是字符串,否则报错 def __repr__(self): return "repr:Person中的repr对象" liulin=Person('刘林',25) print(str(liulin)) # {'name': '刘林', 'age': 25} print(repr(liulin)) #repr:Person中的repr对象 print("%s"%liulin) #{'name': '刘林', 'age': 25} print("%r"%liulin) #repr:Person中的repr对象

class Person: def __init__(self,name,age): self.name=name self.age=age def __repr__(self): return "repr:Person中的repr对象" liulin=Person('刘林',25) print(str(liulin)) print(repr(liulin)) print("%s"%liulin) print("%r"%liulin) #所有值都是 repr:Person中的repr对象 #当类中没有__str__方法时,调用str 会自动执行repr中的代码

class Person: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return str(self.__dict__) #返回的必须是字符串,否则报错 liulin=Person('刘林',25) print(str(liulin)) # {'name': '刘林', 'age': 25} print(repr(liulin)) #<__main__.Person object at 0x0000015D043A7EF0> print("%s"%liulin) #{'name': '刘林', 'age': 25} print("%r"%liulin) #<__main__.Person object at 0x0000015D043A7EF0>
总结:当类中有__str__没有__repr__ ,则调用str可以执行,调用repr返回内存地址
当类中有__repr__没有__str__,则调用str和repr,都执行repr方法中的代码
两个都有,各走各的
__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
# 构造方法 创建一个对象的 # 初始化方法 __init__ 给已经创建出来的对象添加属性 # 析构方法 删除一个对象的时候调用的方法 import time class A: def __init__(self): self.f = open('userinfo','a') def consume(self): pass def __del__(self): '''在删除一个对象之前做一些收尾工作''' self.f.close() print('删除一个对象的时候调用我') a = A() time.sleep(1) del a # 删除一个对象的时候,如果内部存在__del__方法, # 那么在删除一个对象之前先执行__del__方法中的代码
__new__ 构造方法
类创建对象之初进行的函数,常与单例模式一起使用
# new一个对象 class A: def __init__(self): print(111) def __new__(cls): print(222) return object.__new__(cls) #创造对象,将对象返回给__init__ 如果不返回,讲不会执行__init__ a = A() #输出:222 # 111 # 先执行__new__方法 创造出一个对象, # 然后把创造出来的对象传递给__init__方法(先执行new,再执行init) # 会把self自动的返回,被a接收
补充:元类——创建类的类 type() 所有直接用class创建出来的类的元类都是type class 类名(B,classMeta = 元类名) class 类名(B,classMeta = type) 默认 元类 创造 类 所以所有的类的type都是它的元类,默认是type 类 创造 对象 具体创造对象的方法 __new__方法,所有的对象的type都是它对应的类 设计模式——单例模式—: 一个类 可以被多次实例化 但是同一时间在python的内存中,只能有一个实例
单例模式:
一个普通的类,在实例化的时候,可以同时实例化多个对象(多个对象一起执行,都存在内存地址里),单例模式就是只能存在一个
class A: _instance = None #设置一个空 def __init__(self,name): '''给娃穿衣服''' self.name = name def __new__(cls, *args, **kwargs): '''生娃的过程''' if not A._instance: #当_instance为空时,进入此条件 A._instance = object.__new__(cls) #创造对象,赋给_instance,返回 return A._instance #当_instance不为空时,说明已经实例化一次,则直接返回之前那得对象 a1 = A('liu') # 第一次实例化的时候创造一个实例 print(a1.name) #打印liu a2 = A('lin') print(a1.name,a2.name) #打印 lin lin 因为只允许实例化一次,两次实例化是内存地址一样,所以两个值一样

class A: def __init__(self,name): '''给娃穿衣服''' self.name = name def __new__(cls, *args, **kwargs): '''生娃的过程''' if not hasattr(A,'_instance'):#判断如果没有此对象 A._instance = object.__new__(cls) return A._instance a1 = A('alex') # 第一次实例化的时候创造一个实例 print(a1.name) #alex a2 = A('egon') print(a1.name,a2.name) #egon egon
3、item系列
__getitem__ 找 __setitem__ 新建 __delitem__ 删除 __delattr__ 删除
通过上述方法 实现类似字典一样的操作
class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): print(self.__dict__[item]) def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): print('del obj[key]时,我执行') self.__dict__.pop(key) def __delattr__(self, key): print('del obj.key时,我执行') del self.__dict__[key] f1=Foo('sb') f1['age']=18 f1['age1']=19del f1['age'] f1['name']='liulin' print(f1.__dict__)
__call__
对象名加括号,调用类中内置__call__ 方法
class A: def __call__(self): print('执行我了') A()() #实例化 () #执行我了
__hash__
# hash
# 不可变的数据类型都可以被hash
# dict的key set的元素
# dic key --> value
# dic[key] = value

class A: def __init__(self): self.a = 1 self.b = 2 def __hash__(self): return hash(str(self.a)+str(self.b)) a = A() print(hash(a))
依据hash和set(集合)完成的金融面试题
# 金融公司面试题 # 有一个类,对应这个类产生了100个对象 # 每个对象有三个属性 : 姓名 年龄 性别 # 请对这一百个对象进行去重,如果姓名和性别相同,即便年龄不同也是相同的对象 # 问最简便的方法? class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __hash__(self): return hash('%s%s'%(self.name,self.sex)) def __eq__(self, other): if self.name == other.name and self.sex == other.sex: return True p_lst = [] for i in range(100): p_lst.append(Person('egon',i,'male')) p_lst.append(Person('alex',i,'male')) p_lst.append(Person('yuan',i,'male')) print(p_lst) print(set(p_lst))
收获1
对于一些python当中已经存在的内置函数 内置数据类型 内置模块中的方法
都有可能依赖于类中的内置方法
收获2
set方法依赖集合中元素对象的__hash__ __eq__