快捷搜索:

对于新手来说,Python 中有哪些难以理解的概念?

熟手在行都是重新手一途经来的,提起Python中难以理解的观点,可能很多人对付Python变量赋值的机制有些疑心,不过对付习气于求根究底的法度榜样员,只有深入理解了某个事物本色,掌握了它的客不雅规律,才能轻车熟路、运用自若,进阶更高层次来看待这个事物,此刻“火头解牛”这个针言能够贴切表达这个意思,你望见的是整头的牛,而我望见的是牛的内部肌理筋骨,便是这个状态!!!

那么为什么Python变量赋值的机制难以理解呢?

我想可能是我们的思维被C说话变量赋值的机制所固化了。在C说话中变量所分配到的地址是内存空间中一个固定的位置,当我们改变变量值时,对应内存空间中的值也响应改变。在Python中变量存储的机制是完全不一样的,当给一个变量赋值时首先说冥器会给这个值分配内存空间,然后将变量指向这个值的地址,那么当我们改变变量值的时刻说冥器又会给新的值分配另一个内存空间,再将变量指向这个新值的地址,以是和C说话比拟,在Python中改变的是变量所指向的地址,而内存空间中的值是固定不变的。

接下来我们要由浅入深的去验证下我们的结论。在Ubuntu 16.04 LTS 32 位的情况下经由过程id措施查看变量的内存地址的要领来进行验证,为什么要强调情况呢?由于不合的情况下测试结果可能会因为说冥器的优化不合而有所不合。

那这里我们就以Python的int类型为例,可以看到履行 i += 1 后,变量i的内存地址会发生变更,事实上 i += 1 并不是在原有变量i的地址上加1,而是从新创建一个值为6的int工具,变量i则引用了这个新的工具,是以当变量i和变量j的值相同时会指向同个内存地址。同样以Python的float 类型为例也验证了这个变量存储治理的机制。

陆陆续续的试了列表、字典、字符串、元组等变量类型赋值的效果,我发明着实Python中的工具分为可变类型和弗成变类型,列表、字典是可变类型,而整数、浮点、短字符串、元组等是弗成变类型。可变类型的变量赋值与我们懂得的C说话机制相同,而弗成变类型的变量赋值时,实际上是从新创建一个弗成变类型的工具,并将原本的变量从新指向新创建的工具,当然假如没有其他变量引用原有工具时,原有工具就会被收受接收。这也是Python作为动态类型说话的特征,即变量不必要预先声明类型,当变量在赋值时说冥器会根据值的类型创建对应的内存空间进行存储,并将变量指向这个地址空间即可,比如运行a=1时,说冥器将变量指向整形值1的地址,当运行a=0.1时,说冥器将变量指向浮点值0.1的地址。

然则问题又来了!!!为什么Python可以这样毫无所惧地完成动态类型的特性?

这里要追究到PyObject这个布局体的层面。平日来说,无论什么说话终极被谋略机识别到的都是内存中的字节信息,工具实际上便是在更高的层次上把内存上的数据作为一个整体来斟酌,比如一个整数或是一个字符串。Python中所有的器械都是工具,它们拥有一些相同的内容,这些内容定义在PyObject这个布局体中。

ob_refcnt是一个整形变量,它的感化是实现引用计数机制。比如一个工具A,当有一个新的PyObject *引用该工具时,A的引用计数增添;而当这个PyObject *被删除时,A的引用计数削减。当A的引用计数削减到0时,A就可以从堆上被删除,以开释出内存供其余工具应用。ob_type是一个指向_typeobject布局体的指针,这个布局表实际上也是一个工具,它是用来指定一个工具类型的类型工具,这个类型工具记录了不合的工具所需的内存空间的大年夜小信息。那么简单的说,Python中工具机制的核心一个是引用计数,一个便是类型。

PyObject是一个定长工具的布局体,对付可变长度工具的布局体是PyVarObject,它比PyObject布局体多一个ob_size变量,用于指定容器中包孕的元素数量。比如list中有5个元素,那么PyVarObject.ob_size的值便是5。PyVarObject实际上只是对PyObject的一个扩展而已,任何一个PyVarObject所占用的内存,开始部分的字节定义和PyObject是一样的。这就可以解释说,当Python创建一个整形工具PyIntObject,首先它会为这个工具分配内存,并进行初始化,然后这个工具会由一个PyObject*变量来掩护,由于每一个工具都拥有相同的工具头部,这使得工具的引用变得异常的统一。无论工具实际上的类型是什么,只必要经由过程PyObject*指针就可以引用随意率性的一个工具。

深入浅出了Python变量赋值的机制今后,大年夜家就不感觉这是难以理解的观点了吧,着实进修的乐趣就体现在恍然大年夜悟、意会贯通的那一时候。

您可能还会对下面的文章感兴趣: