3.0 序

我们知道python中的字符串属于变长对象,当然和int也是一样,底层的结构体实例所维护的数据的长度,在对象没有定义的时候是不知道的。当然如果是python2的话,底层PyIntObject维护的就是一个long,显然在没创建的时候就知道是1。

可变对象维护的数据的长度只能在对象创建的时候才能确定,举个例子,我们只能在创建一个字符串或者列表时,才知道它们所维护的数据的长度,在此之前,我们对此是一无所知的。

注意我们在前面提到过可变对象和不可变对象的区别,在变长对象中,实际上也可以分为可变对象和不可变对象。list和str实例化之后都是变长对象,但是list实例所维护数据是可以动态变化的,但是str实例就不支持添加、删除等操作了。下面我们来研究一下python变长对象中的不可变对象。

3.1 PyUnicodeObject和PyObject_Type

在Python中,PyUnicodeObject是对字符串对象的实现。PyUnicodeObject是一个拥有可变长度内存的对象,这一点很好理解。因为对于表示"hi"和"satori"的两个不同的PyUnicodeObject对象,其内部所需要保存字符串(或者说n个char)的内存空间显然是不一样的。与此同时,PyUnicodeObject又是一个不可变对象,一旦创建之后,内部维护的数据就不可以再修改了。这一特性使得PyUnicodeObject对象可以作为dict的key;但与此同时,当进行多个字符串连接等操作时,也会使效率大大降低。

我们看看PyUnicodeObject的定义:

typedef struct {
PyCompactUnicodeObject _base;
union {
void *any;
Py_UCS1 *latin1;
Py_UCS2 *ucs2;
Py_UCS4 *ucs4;
} data; /* Canonical, smallest-form Unicode buffer */
} PyUnicodeObject; typedef struct {
PyASCIIObject _base;
Py_ssize_t utf8_length; /* Number of bytes in utf8, excluding the
* terminating \0. */
char *utf8; /* UTF-8 representation (null-terminated) */
Py_ssize_t wstr_length; /* Number of code points in wstr, possible
* surrogates count as two code points. */
} PyCompactUnicodeObject; typedef struct {
PyObject_HEAD
Py_ssize_t length; /* Number of code points in the string */
Py_hash_t hash; /* Hash value; -1 if not set */
struct {
unsigned int compact:1;
unsigned int ascii:1;
unsigned int ready:1;
unsigned int :24;
} state;
wchar_t *wstr; /* wchar_t representation (null-terminated) */
} PyASCIIObject;

可以看到PyUnicodeObject实现起来很复杂,这是因为在python中,默认都是Unicode。直接分析起来很费劲,我们可以阅读一篇文章,来看看python在存储字符串的时候是如何节省内存的,从而进一步认识PyUnicodeObject。链接如下:https://rushter.com/blog/python-strings-and-memory/,这里我给翻译一下。

python在存储字符串的时候如何节省内存

从python3开始,str类型使用的是Unicode。而根据编码的不同,Unicode的每个字符最大可以占到4字节,从内存的角度来说, 这种编码有时会比较昂贵

为了减少内存消耗并且提高性能,python的内部使用了三种方式表示Unicode

  • 每个字符一字节(Latin-1 编码)
  • 每个字符二字节(UCS-2 编码)
  • 每个字符四字节(UCS-4 编码)

在python编程中,所有字符串行为都是一致的,而且大多数时间我们都没有注意到差异。然而在处理大文本的时候,这种差异就会变得异常显著、甚至有些让人出乎意料

为了看到内部表示的差异,我们使用sys.getsizeof函数,返回一个对象所占的字节数

# -*- coding:utf-8 -*-
# @Author: WanMingZhu
# @Date: 2019/10/25 14:01
import sys
string = "hello"
print(sys.getsizeof(string)) # 54 # 1 bytes
print(sys.getsizeof(string + "!") - sys.getsizeof(string)) # 1 string2 = "你"
# 2 bytes
print(sys.getsizeof(string2 + "好") - sys.getsizeof(string2)) # 2
print(sys.getsizeof(string2)) # 76 string3 = "

《python解释器源码剖析》第3章--python中的str对象的更多相关文章

  1. 《python解释器源码剖析》第13章--python虚拟机中的类机制

    13.0 序 这一章我们就来看看python中类是怎么实现的,我们知道C不是一个面向对象语言,而python却是一个面向对象的语言,那么在python的底层,是如何使用C来支持python实现面向对象 ...

  2. 《python解释器源码剖析》第12章--python虚拟机中的函数机制

    12.0 序 函数是任何一门编程语言都具备的基本元素,它可以将多个动作组合起来,一个函数代表了一系列的动作.当然在调用函数时,会干什么来着.对,要在运行时栈中创建栈帧,用于函数的执行. 在python ...

  3. 《python解释器源码剖析》第9章--python虚拟机框架

    9.0 序 下面我们就来剖析python运行字节码的原理,我们知道python虚拟机是python的核心,在源代码被编译成字节码序列之后,就将有python的虚拟机接手整个工作.python虚拟机会从 ...

  4. 《python解释器源码剖析》第0章--python的架构与编译python

    本系列是以陈儒先生的<python源码剖析>为学习素材,所记录的学习内容.不同的是陈儒先生的<python源码剖析>所剖析的是python2.5,本系列对应的是python3. ...

  5. 《python解释器源码剖析》第1章--python对象初探

    1.0 序 对象是python中最核心的一个概念,在python的世界中,一切都是对象,整数.字符串.甚至类型.整数类型.字符串类型,都是对象.换句话说,python中面向对象的理念观测的非常彻底,面 ...

  6. 《python解释器源码剖析》第11章--python虚拟机中的控制流

    11.0 序 在上一章中,我们剖析了python虚拟机中的一般表达式的实现.在剖析一遍表达式是我们的流程都是从上往下顺序执行的,在执行的过程中没有任何变化.但是显然这是不够的,因为怎么能没有流程控制呢 ...

  7. 《python解释器源码剖析》第8章--python的字节码与pyc文件

    8.0 序 我们日常会写各种各样的python脚本,在运行的时候只需要输入python xxx.py程序就执行了.那么问题就来了,一个py文件是如何被python变成一系列的机器指令并执行的呢? 8. ...

  8. 《python解释器源码剖析》第7章--python中的set对象

    7.0 序 集合和字典一样,都是性能非常高效的数据结构,性能高效的原因就在于底层使用了哈希表.因此集合和字典的原理本质上是一样的,都是把值映射成索引,通过索引去查找. 7.1 PySetObject ...

  9. 《python解释器源码剖析》第4章--python中的list对象

    4.0 序 python中的list对象,底层对应的则是PyListObject.如果你熟悉C++,那么会很容易和C++中的list联系起来.但实际上,这个C++中的list大相径庭,反而和STL中的 ...

  10. 《python解释器源码剖析》第2章--python中的int对象

    2.0 序 在所有的python内建对象中,整数对象是最简单的对象.从对python对象机制的剖析来看,整数对象是一个非常好的切入点.那么下面就开始剖析整数对象的实现机制 2.1 初识PyLongOb ...

随机推荐

  1. es6 实现双链表

    const util = require('util'); /** * 链表节点类 */ class Node { constructor (ele) { this.ele = ele; this.n ...

  2. 【分布式事务】使用atomikos+jta解决分布式事务问题

    一.前言 分布式事务,这个问题困惑了小编很久,在3个月之前,就间断性的研究分布式事务.从MQ方面,数据库事务方面,jta方面.近期终于成功了,使用JTA解决了分布式事务问题.先写一下心得,后面的二级提 ...

  3. Python中类的继承代码实例

    Python中类的继承代码实例 这篇文章主要介绍了Python中类的继承代码实例,本文直接给出代码及运行效果,需要的朋友可以参考下 相对于C 的继承编写,Python更简洁,而且效率也是很高的,下面编 ...

  4. Mac 常用配置(JDK切换,ll命令设置)

    打开 /Users/用户/.bash_profile文件 1.JDK切换,添加如下内容 export JAVA_6_HOME=`/usr/libexec/java_home -v 1.6` # 设置 ...

  5. JAVA_day1_变量和常量

    JAVA变量和常量 一.JAVA中的关键字 注:关键字区分大小写,Try不是关键字而try则是. 二.JAVA标识符 1.标识符:标识符就是用于给 Java 程序中变量.类.方法等命名的符号. 2.标 ...

  6. AFNetworking网址中有中文崩溃的问题

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; manager.responseSe ...

  7. web赛题3

    2019--21省赛 wp:https://xz.aliyun.com/t/6458 2019-11-22蚂蚁金服(南邮)wp有了,微信 https://platform.d3ctf.io/#/ @d ...

  8. 小林的VB6動態壁紙模擬程序

    本項目參考了以下資料[這可能對你理解程序運行有幫助]: https://github.com/Yinmany/WinWallpaper https://blog.csdn.net/breaksoftw ...

  9. 【VS开发】OpenCV2:Mat属性type,depth,step

    OpenCV2:Mat属性type,depth,step 在OpenCV2中Mat类无疑使占据着核心地位的,前段时间初学OpenCV2时对Mat类有了个初步的了解,见OpenCV2:Mat初学.这几天 ...

  10. 【计算机视觉】time of flight (TOF)

    目录(?)[-] 11 TOF初探 12 TOF研究机构 13 TOF之应用领域 14 TOF相机特点 2 深度相机比较 1 MESA系列介绍 2 PMD Tec系列 3 NATAL 4 primeS ...