类的内置方法
内置方法之 __str__()
可以改变返回值,以前是地址,那么使用这个方法之后,打印的就是这个内容,而不是地址,使用print方法的时候,默认调用这个方法
class A(): def __init__(self,name,price,period): self.name = name self.price= price self.period= period def __str__(self): # 当定义这个方法之后,类外的调用对象参数的print就会变成调用这个方法
# '''打印这个对象的时候 自动触发__str__'''
# '''使用%s进行字符串的拼接的时候 自动触发__str__'''
return '%s,%s,%s'%(self.name,self,price,self,period) python = Course('python',40000,'6 month') print(python)
内置方法之__repr__()
功能和str功能一致,但是repr是备胎,只有找不到str的时候才调用这个方法
class Course: def __init__(self,name,price,period): self.name = name self.price = price self.period = period def __repr__(self): # 备胎 return '%s,%s,%s'%(self.name,self.price,self.period) def __str__(self): return self.name python = Course('python',25000,'6 months') print(python) print('course %s'%python) print(f'course {python}') print(repr(python)) print('course %r'%python)
# 如果str存在,repr也存在
# 那么print(obj)和使用字符串格式化format,%s这两种方式 调用的都是__str__
# 而repr(obj)和%r格式化字符串,都会调用__repr__
# 如果str不存在,repr存在
# 那么print(obj),字符串格式化format,%s,%r 和repr(obj)都调用__repr__
# 如果str存在,repr不存在
# 那么print(obj)和使用字符串格式化format,%s这两种方式 调用的都是__str__
# repr(obj)和%r格式化字符串 都会打印出内存地址
在类的继承中的查找:
class Course(object): def __init__(self,name,price,period): self.name = name self.price = price self.period = period def __repr__(self): # 备胎 return '%s,%s,%s'%(self.name,self.price,self.period) # def __str__(self): # return self.name class Python(Course): pass # def __repr__(self): # 备胎 # return '%s--%s--%s'%(self.name,self.price,self.period) # def __str__(self): # return '全栈开发 :'+self.name py20 = Python('python',25000,'6 months') print(py20) # 打印对象 先走自己的str,如果没有,走父类的,如果除了object之外的所有父类都没有str # 再回来,找自己的repr,如果自己没有,再找父类的 # repr是str的备胎 # 和所有的字符串格式化以及直接打印这个对象相关 # str(obj),repr(obj)
这两个内置方法的作用:
# 有了repr或者str在打印对象的时候 就不会显示用户不关心的内存地址了
# 增强了用户的体验 在程序开发的过程中
# 如果我们需要频繁打印对象中的属性,需要从类的外部做复杂的拼接,实际上是一种麻烦
# 如果这个拼接工作在类的内部已经完成了,打印对象的时候直接就能显示
内置方法之__new__()
new方法时构造方法
class Foo: def __new__(cls, *args, **kwargs): print('in new') # 先执行 obj = object.__new__(cls) print(obj) return obj def __init__(self): print('init',self) # 后执行 Foo() # 如果有new 方法,那么会先执行new方法,然后再执行init方法
# 实例化一个Foo的对象
# 先开辟一块儿空间,使用的是Foo这个类内部的__new__
# 如果我们的Foo类中是没有__new__方法的
# 调用object类的__new__方法了
class Foo(object): def __new__(cls, *args, **kwargs): # cls永远不能使self参数,因为#self在之后才被创建 obj = object.__new__(cls) # self是在这里被创造出来的 print('new : ',obj) return obj def __init__(self): print('init',self) Foo() # 在使用self之前,都还有一个生产self的过程 # 就是在内存中开辟一块属于这个对象的空间,并且在这个空间中存放一个类指针 # 以上就是__new__做的所有事情
单例模式
# 设计模式 - 单例模式 # 一个类 有且只能有一个实例 class A:pass a1 = A() a2 = A() print(a1) print(a2) class A: __flag = None def __new__(cls, *args, **kwargs): if cls.__flag is None: cls.__flag = object.__new__(cls) return cls.__flag def __init__(self,name=None,age=None): self.name = name if age: self.age = age a1 = A('alex',84) print(a1) a2 = A('alex',83) print(a2) a3 = A('alex') print(a3) print(a1.age) # 保证一个类无论 被实例化多少次,只开辟一次空间,始终使用的是同一块内存地址
内置方法之__del__()
# __del__方法 # python解释器 import time class A: def __init__(self,name,age): self.name = name self.age = age def __del__(self): # 只和del obj语法有关系,在执行del obj之前会来执行一下__del__中的内容 print('执行我啦') a = A('alex',84) print(a.name) print(a.age) # del a # 这个变量已经没了 time.sleep(1) # 在所有的代码都执行完毕之后,所有的值都会被python解释器回收 # python解释器清理内存 # 1.我们主动删除 del obj # 2.python解释器周期性删除 # 3.在程序结束之前 所有的内容都需要清空 import time class A: def __init__(self,path): self.f = open(path,'w') def __del__(self): '''归还一些操作系统的资源的时候使用''' '''包括文件\网络\数据库连接''' self.f.close() a = A('userinfo') time.sleep(1)
with的上下文处理
# with的上下文处理 class File: def __enter__(self): # 在with执行之前先执行 print('start') def __exit__(self, exc_type, exc_val, exc_tb):# with执行完之后执行 print('exit') with File(): print('wahaha') class myopen: def __init__(self,path,mode='r'): self.path = path self.mode = mode def __enter__(self):# 在with执行之前先执行 print('start') self.f = open(self.path,mode=self.mode) return self.f def __exit__(self, exc_type, exc_val, exc_tb):# with执行完之后执行 self.f.close() print('exit') with myopen('userinfo','a') as f: f.write('hello,world')