Python-容易想不起来的东东

阅读目录:

  1、import sys

   2、__slots__

  3、未实现和未实现异常

  4、运算符重载中的反向方法

  5、生成器交互:

  6、引用计数

  7、命名元组nametuple

  8、待续。。。。。

 

 

 

 

1、import sys  -----sys.exit(100) 退出状态码

2、__slots__

  问题引出:都是字典惹的祸。

  字典为了提升查找效率,必须用空间换时间。hash算法是散列算法,将数据散列到某个空间的不同位置,所以需要开辟一个足够的空间。

  也就是空间换时间,一般来说一个对象,属性对一点,都存储在字典中便于查询,问题不大。但是如果数百万个对象,那么字典占得就有点大了

  这个时候,如果需要,可以把属性字典__dict__省了。

  Python提供了__solts__属性。

  测试1: 

  

  

  

    总结:

      • __slots__ 告诉解释器,实例的属性都叫什么,一般来说,既然要节约内存,最好还是使用元组比较好。
      • 一旦类提供了__slots__,就阻止实例产生__dict__来保存实例的属性。
      • 尝试为实例动态增加属性setattr 或者点的方式, 返回的都是AttributeError,说明实例不能动态增加属性了
      • 当然只影响实例,类还是可以继续做自己的操作。

  测试 2:继承, 不会继承

  

 

  应用场景:使用需要构建在数百万以上对象,且内存容量较为紧张,实例的属性简单,固定且不用动态增加的场景。

      经过测试,即便数百万的对象,也就几百兆,用了__slots__也就几十兆,除非必须,否则第一想法是扩容,而不是在这里纠结。

      实在不行的情况下,再来考虑这些细节,当然写的时候,注意到也很好。

3、未实现和未实现异常

  

  在库中,NotImplemented =None,但是不是 ==  is  None

  

  注意:继承走的是mro这条路,type,__class__ 与继承不是同一条路,type(type)= type

     也就是说类的类型是type

4、运算符重载中的反向方法

  测试 1:

  

  测试2:

  

  测试3:

  

  举例测试:对上面的举例

  

  解决 1+a   a+1 问题:

  

  参考代码:实现 a+1, 1 + a

 1 #########  方式 1
 2 class A:
 3     def __init__(self, x):
 4         self.x = x
 5     def __add__(self, other):
 6         print('######  A add  #########')
 7         if isinstance(other, type(self)):
 8             return  self.x + other.x
 9         else:
10             return self.x + other
11     def __iadd__(self, other):
12         print('######  iadd  #########')
13         return type(self)(self.x + other.x)
14     def __radd__(self, other):
15         print('######  radd  #########')
16         if isinstance(other, type(self)):
17             return  self.x + other.x
18         else:
19             return self.x + other
20 
21 a = A(4)
22 print(a + 1)
23 print(1 + a)
24 
25 
26 ###########  方式 2 减少程序的冗余
27 class A:
28     def __init__(self, x):
29         self.x = x
30     def __add__(self, other):
31         print('######  A add  #########')
32         if hasattr(other, 'x'):
33             return  self.x + other.x
34         else:
35             try:
36                 x = int(other)
37             except:
38                 x = 0
39             return self.x + x
40     def __iadd__(self, other):
41         print('######  iadd  #########')
42         return type(self)(self.x + other.x)
43     def __radd__(self, other):
44         print('######  radd  #########')
45         return self + other
46 
47 a = A(4)
48 print(a + 1)
49 print(1 + a)
两种方式

 

  联想 路径重载:

1 from  pathlib import  Path
2 
3 p = Path('a/b')
4 p = p / 'c'
5 print(p)
6 p = 'q' / p
7 print(p)
8 
9 print('a' / 'd' / p) # 报错

 

   sub的举例:

    

5、生成器交互:

  send用法:

  

  事实上不推荐使用这种方式,而是使用类封装的方式:如之前写过的 生成一批数据的功能类:

  每次都可以通过传入的值,来改变输出结果。

 1 import  random
 2 
 3 class RandomNum:
 4     @classmethod
 5     def nums(cls, patch, start, stop):
 6         while True:
 7             yield [ random.randint(start, stop)  for _ in range(patch)]
 8 
 9 g = RandomNum.nums(30,3,7)
10 for _ in range(4):
11     print(next(g))

 7、引用计数

1 import sys
2 
3 sys.getrefcount(x)

8、命名元组nametuple :https://www.cnblogs.com/JerryZao/p/9432949.html

posted @ 2018-09-19 22:13  JerryZao  阅读(229)  评论(0编辑  收藏  举报