zoukankan      html  css  js  c++  java
  • 小数据池

    python小数据池(内存地址)

    今天来学习认识一下python中的小数据池。 
    我们都知道 ==是用来作比较,要是两个变量的数值相等, 
    用==比较返回的bool值会是True:

    n = 100
    m = 100
    print(m == n)  # 数值上的相等-True

    如果我们用m is n这样的方式呢? 
    注意要测试内存地址is()和接下来的id()方法等都不要在pyCharm (python IDE)中测试, 
    而是要打开python自带的IDE或直接cmd环境下测试才能得出效果。 

    is 比较的是内存地址:

    “==” 和 “is” 的区别:

    前者是相等性比较, 
    比较的是两个对象中的值是否相等,后者是一致性比较,比较的是两个对象的内存空间地址是否相同。

    如果内存地址相同,那么它们的值肯定也是一样的,因此,如果 “is” 返回 True,那么 “==” 一定也返回 True,反之却不成立。有且当仅比较的两个变量指向同一个对象时 “is” 才返回 True,而 “==” 最终取决于对象的 eq() 方法,本质上两个变量进行 “==” 比较操作调用的是对象的 eq() 方法。

    查看内存地址我们使用的是id()方法: 

    将m 和 n都赋值整型值255,256,257。 
    分别进行is操作时,却发现两者的布尔值结果不同。后面会出现为False 
    为什么呢? 
    为什么值一样,256前面的内存是相同的,257就不想等了。这说明是有某种限制的

    这是由python中的整型对象的缓冲池机制引起的。

    小数据池 (注意只有字符串和数值有这个概念)

    在一定范围之内的,共用同一个内存地址。 
    数字 -5~256 节省空间(内存),共用的都是一个小数据池(指向的是同一个内存地址)

    小整数对象[-5, 257]在python中是共享的 
    (注,用列表表示是因为python中含首不含尾,所以[-5,257]表示的范围也就是数字 -5~256。) 
    整数对象都是从缓冲池中获取的。 
    整数对象回收时,内存并不会归还给系统,而是将其对象的ob_type指向free_list,供新创建的整数对象使用

    1.小整数对象——小整型对象池

    [small_ints的链表] 
    在实际编程中,数值比较小的整数,比如1,2,33等,会非常频繁的出现。 
    python中,所有的对象都存在于系统堆上。 
    如果某个小整数出现的次数非常多,那么python将会出现大量的malloc/free操作,这样大大降低了运行效率,而且会造成大量的内存碎片,严重影响Python的整体性能。 
    所以在python2.5乃至3.6中,将小整数位于[-5,257)之间的数,缓存在小整型对象池中。

    2.大整数对象——通用整数对象池

    python将小整型数完全的缓存在了小对象缓存池中了。 
    而那些大整数对象呢? 
    python运行环境也有提供一块内存空间供大整数轮流使用。 
    这块内存空间就是PyIntBlock。 
    通常称为通用整数对象池。 
    所以大整数其实也是有缓存的。 
    该对象池使用链表组织,哪怕两个大整数变量有着相同的值,但是在链表中确是不同的节点。不再是一个对象了。

    字符串intern

    关于字符串的intern内存驻留机制: 

    在计算机科学中,string interning是一种只存储每个不同字符串值的onecopy的方法,它必须是不可变的。连接字符串使得一些stringprocessing任务更费时——或者更节省空间,因为在创建或插入字符串时需要moretime。不同的值存储在字符串驻留池中。

    也就是说值相同的字符串对象只会保存一份,是共用的,所以字符串必须是不可变对象。 
    就跟小整数对象一样,相同的数值只要保存一份就行了,没必要用不同对象来区分。

    同时以上也说到了这样做的优缺点:

    优点:能够提高一些字符串处理任务在时间和空间上的性能;需要值相同的字符串的时候(比如标识符),直接从池里拿来用,避免频繁的创建和销毁,提升效率,节约内存。

    缺点:在创建或插入字符串时会花费更多的时间。

    注意事项

    1、拼接字符串

    由于字符串的改动不是inplace的操作,需要新建对象,因此不推荐使用+来拼接字符串,推荐使用join函数,因为join函数在拼接字符串之前会计算所有字符串的长度,然后逐一拷贝,仅新建一次对象。

    2、字符串驻留限制

    仅包含下划线(_)、字母和数字的字符串会启用字符串驻留机制驻留机制。因为解释器仅对看起来像python标识符的字符串使用intern()方法,而python标识符正是由下划线、字母和数字组成。

    python默认只会对由字符 
    “0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz”构成字符串进行intern。

    这部分的逻辑在codeobject.c中的函数PyCode_New中:在该函数中,会调用all_name_chars,检查字符串是否全是由简单的字符组成,判断通过的字符串才会进行intern处理。

  • 相关阅读:
    设计模式笔记4(工厂模式)
    设计模式笔记4(工厂模式)
    以前写的东东,放在这里个索引吧
    sicily 1001. Black Magic
    沙漠之旅
    hdu 1395(2^x mod n = 1)
    hdu 2161(Primes)
    sicily 8058. Matrix
    十进制转换为二进制
    硬币水题II
  • 原文地址:https://www.cnblogs.com/z18271397173/p/9526140.html
Copyright © 2011-2022 走看看