zoukankan      html  css  js  c++  java
  • Python中容易忽视的知识点

    今天坐在实验室,觉得有点无聊,想了下,很久没写博客了,就来写一点,正好遇到了一个有意思的小问题,分享给大家。

    首先我们通过一个小的实验来看一下内容:

    不管是 Python2 还是 Python3 环境下,只要你是在 CPython 的交互式命令行 REPL 中执行,结果没什么不同。

    我们知道 is 比较的是两个对象的内存地址是否一样( id 函数返回一个和对象的内存地址相关的值),言外之意就是看我所给的两个变量是否指向同一个对象。我们来看看每个变量的 id 值。

    此处请忽略我的输入法皮肤,很多人都说这只狗比较嚣张,我认为只是看起来的单纯的比较贱而已,哈哈哈。(跑偏了。。。)

    不出所料,前后两组 a,b的 id 值是相同的,只有中间这组 id 值不一样,我们可以对其简单分析一下原因。在 Python 中,一切皆为对象,理论上任意两个对象的 id 值都是不一样的,例如:

    看得出每个对象的 id 值是不同的,哪怕两个对象的值(内容)相同,他们的 id 值也是不一样的(tuple2和tuple3)。那为什么前面第一组两个对象的id值相同呢?可能有些同学已经知道了

    因为在 Python 中,我们需要使用对象的时候 Python 就会为我们创建好,当不需要了它就会进行回收,就好比屋子里面的东西用完之后,要及时清理,否则整个屋子很快就会堆满,最终导致房间再也塞不进任何东西。

    同样的,为了提高性能,Python 就把一些常用的整数专门缓存起来,就像屋子里面有些东西总是每天都要频繁使用,比如床,你不能说睡完之后,就把床搬出去,要用了再搬回来,这样的效率太低,因为这个搬运过程实在是太耗时了。于是,我们可以专门拿一块空间用来放置这个床。

    Python 中也是同样的道理,因为整数是我们经常使用的对象,为了避免重复的创建、回收,干脆就把那些常用的整数缓存起来,每次需要使用时直接从缓存中拿,而不是重新创建(重新创建的话,肯定是一个全新的对象)。这些整数的范围是[-5, 256],当然这个数字范围是Python之父决定的,你要改,必须重新编译Python环境。

    现在我们就能解释第一组为什么是True,第二组为什么是False了。为什么第三组结果又是 True 了?,不是说好大于256的整数不再缓存,每次使用都是新对象吗?别急,再听我啰嗦一下。

    还是出于性能考虑,Python内部做了进一步优化,怎么优化呢?但凡是在同一个代码块中的代码,如果出现两个值相同的整数,那么它们将被重用,来看下面这个代码:

    # -*- coding: utf-8 -*-
    # 作者:    ZFJ
    # 创建时间:2019/7/510:47
    # 文件:    Python_id()检测.py
    # IDE:     PyCharm
    
    a = 257
    b = 257
    
    
    def func():
        c = 257
        # 此处的结果应该为:False
        print(a is c)
    
    
    # 此处的结果应改为:True
    print(a is b)
    func()

    上面代码是在一个 Python_id()检测.py 文件中,运行时,a和b的id值相同,而c的id值与a不一样,因为a、b 在同一个代码块,属于模块级别,而 c 是在函数里面,属于局部变量,他们不属于同一代码块中,因此函数里面的 257 这个对象时会重新创建,而创建 b 的时候,发现同级代码块中有个257的值了,就重用了这个对象。

    再回到前面讲的第三组值,在 Python 的交互式命令行 REPL 中,每单独一行都视为一个代码块,同一行中的代码属于同一个代码块,因此不难理解,第三组中的a和b处在同一个代码块中,所以后者重用了前者,因此,两个变量的id是相同的。

    有没有觉得这是一个坑。虽然我们实际场景中并不一定能用上,但是至少我们知道了Python为我们做的一些优化工作。

  • 相关阅读:
    Vue+Element-UI+jQuery+Layer+Camera+Easing的简单应用
    Vue(vue-cli脚手架)中使用layer.js做非模态弹窗(二)
    unicable
    grep 搜索目录时,怎样排除某些目录?
    Mali Midgard架构解析
    如何从GFP确定最后申请的内存来自哪个zone?
    内存申请 GFP_KERNEL GFP_ATOMIC
    Linux内核中的page migration和compaction机制简介
    IOVA/IOMMU
    memory zone spanned/present/managed区别
  • 原文地址:https://www.cnblogs.com/ZFJ1094038955/p/11136973.html
Copyright © 2011-2022 走看看