内置方法 双下方法 魔术方法: 都是python的对象内部自带的 并且都不需要我们自己去调用它
1. __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) #return 类型必须是str def __str__(self): return self.name #return的类型必须是str python = Course(‘python‘, 25000, ‘6 months‘) print(python) #-->python print(‘course %s‘ % python) #-->course python print(repr(python)) #-->python,25000,6 months print(‘course %r‘ % python) #-->course python,25000,6 months
总结:
如果__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) #return类型必须是str def __str__(self): return self.name #return类型必须是str 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的备胎和所有的字符串格式化以及直接打印这个对象相关 推荐使用repr
2. __new__ 构造方法 生产对象的时候用的 - 单例模式
实例化一个Foo的对象 先开辟一块儿空间,使用的是Foo这个类内部的__new__ 如果我们的Foo类中是没有__new__方法的,则调用object类的__new__方法
class Foo: def __new__(cls, *args, **kwargs): #cls永远不会使用self参数,因为self 是这之后才被创建出来的 print(‘in new‘) # 先执行 obj = object.__new__(cls) #self空间在这一步才创建出来 print(obj) return obj #将创建出来的空间返回给self def __init__(self): print(‘init‘) print(self) # 后执行 Foo() ‘‘‘ in new <__main__.Foo object at 0x000001D5A4A27400> init <__main__.Foo object at 0x000001D5A4A27400> obj和self内存地址一样 ‘‘‘
单例模式:
一个类有且只能有一个实例:可以被实例化多次 但是保留最后一次实例化的属性
#单例模式 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): if name: self.name = name if age: self.age = age a1 = A(‘alex‘,84) print(a1) #<__main__.A object at 0x00000241BF577BA8> a2 = A(‘alex‘,83) print(a2) #<__main__.A object at 0x00000241BF577BA8> a3 = A(‘alex‘) print(a3) #<__main__.A object at 0x00000241BF577BA8> print(a1.__dict__) #{‘name‘: ‘alex‘, ‘age‘: 83} print(a2.__dict__) #{‘name‘: ‘alex‘, ‘age‘: 83} print(a3.__dict__) #{‘name‘: ‘alex‘, ‘age‘: 83} # 保证一个类无论 被实例化多少次,只开辟一次空间,始终使用的是同一块内存地址
3. __del__方法
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 # 手动删除对象a 就直接执行__del__ time.sleep(1) # 如果不手动执行del 会在所有代码执行完成后 自动执行del a 这时候就会先睡一秒在打印‘__del__‘中的内容 # 在所有的代码都执行完毕之后,所有的值都会被python解释器回收
python解释器清理内存: 1.我们主动删除 del obj 2.python解释器周期性删除 3.在程序结束之前 所有的内容都需要清空 既然python解释器可以周期性的清理内存 为什么我们还要手动去删除一些数据呢? 因为在归还一些操作系统的资源的时候还有包括文件\网络\数据库连接的时候使用, 我们需要先将这些接口关闭了之后再删除内容,不然内容删除了,这些打开的接口依然存在,会影响后面对系统资源等一些数据的调用
import time class A: def __init__(self,path): self.f = open(path,‘w‘) def __del__(self): ‘‘‘归还一些操作系统的资源的时候使用‘‘‘ ‘‘‘包括文件\网络\数据库连接‘‘‘ print(111) self.f.close() #在删除内存的时候执行__del__ 先将文件接口关闭 a = A(‘userinfo‘) time.sleep(1)
4. __call__
class A: def call(self): #当然也可以自己手动写一个call方法实现和__call__一样的功能 print(‘in call‘) def __call__(self, *args, **kwargs): print(‘in __call__‘) A()() #实例化+调用 相当于obj = A()和obj() #如果没有__call__会报错 ‘A‘ object is not callable obj = A() obj.call() #调用自己写的call方法实现和__call__一样的功能
5 __enter__和__exit__ 用在with的上下文处理
class File: def __enter__(self): print(‘start‘) def __exit__(self, exc_type, exc_val, exc_tb): print(‘exit‘) with File(): print(‘wahaha‘) ‘‘‘ 输出: start wahaha exit
和with组合编写一个文件操作类:
import pickle class Mypickle_dump: #写文件 def __init__(self, path, mode=‘ab‘): self.path = path self.mode = mode def __enter__(self): self.f = open(self.path, self.mode) return self def dump(self, value): pickle.dump(value, self.f) def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() with Mypickle_dump(‘mypickle‘, ‘ab‘)as f: #读文件 f.dump(‘1‘) f.dump(‘2‘) f.dump(‘3‘) f.dump(‘4‘) f.dump(‘你好啊‘) class Mypickle_load: def __init__(self, path, mode=‘rb‘): self.path = path self.mode = mode def __enter__(self): self.f = open(self.path, self.mode) return self def load(self): while 1: try: yield pickle.load(self.f) except EOFError: break def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() with Mypickle_load(‘mypickle‘, ‘rb‘)as f: for i in f.load(): print(i)
with 和装饰器的区别:
都是在一个函数的前后添加功能,但是装饰器装饰一次之后,后面再次使用都是被装饰过的,而with每次使用都得再次调用
import time class Timer: def __enter__(self): self.start = time.time() def __exit__(self, exc_type, exc_val, exc_tb): print(time.time() - self.start) def func(): print(‘wahaha‘) time.sleep(1) print(‘qqxing‘) with Timer(): func()
原文地址:https://www.cnblogs.com/stron/p/10642123.html
时间: 2024-10-08 23:22:07