Pthon面向对象-补充知识
Pthon面向对象-补充知识
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.tracemalloc
标准库tracemalloc,可以统计内存使用情况,通过下面的案例可以看出内存使用上字典还是较为占用空间的。
1 #!/usr/bin/env python 2 #_*_conding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie 5 6 import tracemalloc 7 8 tracemalloc.start() #开始跟踪内存分配 9 10 d = [dict(zip("xy",(5,6))) for i in range(1000000)] #237M 11 12 t = [tuple(zip("xy",(5,6))) for i in range(1000000)] #191M 13 14 snapshot = tracemalloc.take_snapshot() #快照,当前内存分配 15 16 top_stats = snapshot.statistics("lineno") #快照对象的统计 17 18 19 for stat in top_stats: 20 print(stat) 21 22 23 24 #以上代码执行结果如下: 25 D:/Language/Python/Code/Devops/Python基础/07.面向对象编程/魔术方法/13.补充知识.py:10: size=237 MiB, count=1999995, average=124 B 26 D:/Language/Python/Code/Devops/Python基础/07.面向对象编程/魔术方法/13.补充知识.py:12: size=191 MiB, count=3000002, average=67 B 27 D:/Language/Python/Code/Devops/Python基础/07.面向对象编程/魔术方法/13.补充知识.py:14: size=432 B, count=1, average=432 B 28 D:\Language\Python\interpreter\Python37\lib\tracemalloc.py:532: size=64 B, count=1, average=64 B
二.__slots__
应用场景:
使用需要构建在数百万以上众多对象,且内存容量较为紧张,实例的属性简单,固定且不用动态增加的场景。
可以使用tracemalloc看看内存使用的差异。建议使用stats = snapshot.statistics("filename")查看总内存使用。
1 #!/usr/bin/env python 2 #_*_conding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie 5 6 class A: 7 x = 100 8 9 """ 10 "__slots__"魔术方法会告诉解释器,实例的属性都叫上面,一般来说,既然要节约内存,最好还是使用元组比较好。 11 一旦提供了"__slots__",就阻止实例产生"__dict__"来保存实例的属性。 12 """ 13 __slots__ = ("y","z") 14 15 def __init__(self): 16 self.y = 20 17 self.z = 30 18 19 def show(self): 20 print(self.x,self.y) 21 22 class B(A): #B类继承自A类 23 pass 24 25 a = A() 26 a.show() 27 # a.name = "tom" #会抛异常"AttributeError: 'A' object has no attribute 'name'",说明实例不可以动态增加属性了,因为属性已经被"__slots__"提前定义好啦! 28 29 A.name = "Tom" #这是可以的,因为这个是类属性,说明"__slots__"只能限制当前实例而不能限制当前类 30 31 print(A.name) 32 print("A",A.__dict__) 33 print("B",B().__dict__) #可以访问B类实例的"__dict__"属性,说明"__slots__"不影响类实例,不会继续下去,除非子类里面自己也定义了"__slots__" 34 # print(a.__dict__) #抛异常"AttributeError: 'A' object has no attribute '__dict__'",一旦提供了"__slots__",就阻止实例产生"__dict__"来保存实例的属性。 35 print(a.__slots__) 36 37 38 39 #以上代码执行结果如下: 40 100 20 41 Tom 42 A {'__module__': '__main__', 'x': 100, '__slots__': ('y', 'z'), '__init__': <function A.__init__ at 0x00000157A5B05678>, 'show': <function A.show at 0x00000157A5B051F8>, 'y': <member 'y' of 'A' objects>, 'z': <member 'z' of 'A' objects>, '__doc__': None, 'name': 'Tom'} 43 B {} 44 ('y', 'z')
三.未实现和未实现异常
1 #!/usr/bin/env python 2 #_*_conding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie 5 6 print(type(NotImplemented)) 7 print(type(NotImplementedError)) 8 9 print(NotImplemented) #是个值,单值,是"NotImplementedType"类的实例 10 11 12 raise NotImplementedError #是类型,是异常类,返回type 13 14 15 16 #以上代码执行结果如下: 17 <class 'NotImplementedType'> 18 <class 'type'> 19 NotImplemented 20 Traceback (most recent call last): 21 File "D:/Language/Python/Code/Devops/Python基础/07.面向对象编程/魔术方法/13.补充知识.py", line 12, in <module> 22 raise NotImplementedError #是类型,是异常类,返回type 23 NotImplementedError
四.运算符重载中的反向方法
1 #!/usr/bin/env python 2 #_*_conding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie 5 6 class A: 7 def __init__(self,x): 8 self.x = x 9 10 def __add__(self, other): 11 print(self,"add") 12 return self.x + other.x 13 14 def __iadd__(self, other): 15 print(self,"iadd") 16 return A(self.x + other.x) 17 18 def __radd__(self, other): 19 print(self,"radd") 20 return self.x + other.x 21 22 class B: 23 def __init__(self,x): 24 self.x = x 25 26 """ 27 如果不实现"__add__"方法,其实B类也等价于下面注释的代码 28 """ 29 # def __add__(self, other): 30 # if isinstance(other,type(self)): 31 # return self.x + other.x 32 # else: 33 # return NotImplemented 34 35 a = A(10) 36 b = A(20) 37 print(a,b) 38 print(a + b) #调用"__add__"方法 39 print(b + a) 40 b += a #调用"_iadd__"方法 41 a += b #同上 42 43 c = B(30) 44 print(a + c) 45 print(c + a) #这里的c是类B的实例,但是类B没有实现"__add__"方法,就去找a的"_radd__"方法 46 # print(a + "abc") #报错"AttributeError: 'str' object has no attribute 'x'",字符串实现了"__add__"方法,不过默认是处理不了和其它类型的加法,就返回"NotImplemented" 47 # print(1 + a) #报错"AttributeError: 'int' object has no attribute 'x'",整型也实现了"__add__"方法的,不过这个方法对于这种加法的返回值是"NotImplemented",解释器发现在这个值,就会发起第二操作对象的"__radd__"方法的调用。 48 49 50 51 #以上代码执行结果如下: 52 <__main__.A object at 0x000001DFBE585908> <__main__.A object at 0x000001DFBE585988> 53 <__main__.A object at 0x000001DFBE585908> add 54 30 55 <__main__.A object at 0x000001DFBE585988> add 56 30 57 <__main__.A object at 0x000001DFBE585988> iadd 58 <__main__.A object at 0x000001DFBE585908> iadd 59 <__main__.A object at 0x000001DFBE585A48> add 60 70 61 <__main__.A object at 0x000001DFBE585A48> radd 62 70
五.仅位置参数
1 #!/usr/bin/env python 2 #_*_conding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie 5 6 """ 7 2019年10月14日,发布了Python3.8.0,提供了仅位置参数(Positional-only arguments)。 8 """ 9 10 11 def add(x, y=5, /, z=6): 12 print(x + y + z) 13 14 15 add(1, 2, 3) 16 add(1, y=2, z=3) 17 add(x=1, y=2, z=3) 18 add(1, 3, z=5)
六.Python的对象模型
在Python中,任何对象都有类型,可以使用type()或者 __class__ 查看。
但是类型也是对象即类对象,它也有自己的类型。
所有新类型的缺省类型是type(可以使用元类来改变) 特殊类型type是所有对象的缺省类型,也包括type自己。但它又是一个对象,因此从object继承特殊类型object是继承树的顶层,它是python所有类型的最终基类
也就是说,继承都来自object,类型都看type。type也是对象继承自object,object也有类型是type。 这俩又特殊,type类型是它自己,object没有基类。
七.断言语法
1 #!/usr/bin/env python 2 #_*_conding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie 5 6 a = 100 7 8 assert a > 80,"对变量a进行断言,即如果a大于80则条件成立不做任何处理,否则抛出异常" 9 10 print("{0} 我是分隔符 {0}".format("*" * 30)) 11 12 assert a < 100,"对变量a进行断言,即如果a小于100则条件成立不做任何处理,否则抛出异常"
当你的才华还撑不起你的野心的时候,你就应该静下心来学习。当你的能力还驾驭不了你的目标的时候,你就应该沉下心来历练。问问自己,想要怎样的人生。
欢迎交流学习技术交流,个人微信: "JasonYin2020"(添加时请备注来源及意图备注)
作者: 尹正杰, 博客: https://www.cnblogs.com/yinzhengjie/p/11802229.html