str=--python语言程序设计--,python中str函数可以实现

  str=\"python语言程序设计\",python中str函数可以实现

  本文主要介绍Python内置str的源代码学习。有需要的朋友可以借鉴一下,希望能有所帮助。祝大家进步很大,早日升职加薪。

  00-1010简介1 Unicode 2.1 Unicode 2.1 Unicode对象在Python中的好处2.2 Python对Unicode的优化3 Unicode对象的底层结构3.1 PyasciiObject 3.2 PyCompactionCodeObject 3.3 PyunicodeObject 3.4示例4 interned机制5摘要

  

目录

  “深度理解Python内置类型”的内容将从源码的角度向大家介绍Python中各种常用的内置类型。

  在介绍常见类型str之前,在上一篇博客:Python源码学习笔记:深入了解Python内置类型——bytes中,我们已经介绍了与str密切相关的字节的源码知识。本博客回顾了str相关源代码的分析。

  

引言

  计算机存储的基本单位是字节,由8位组成。由于英文只是由26个字母加上一些符号组成,所以英文字符可以直接以字节保存。但是,其他语言(如中国、日本、韩国等。)由于字符量大,不得不用多个字节编码。

  随着计算机技术的普及,非拉丁字符编码技术得到了发展,但仍然存在两大局限性:

  不支持多语言:一种语言的编码方案不能在另一种语言中使用,没有统一的标准:比如中文有很多编码标准,如GBK、GB2312、GB18030等。由于编码方式不统一,开发者需要在不同的代码之间来回转换,不可避免的会出现很多错误。为了解决这种不一致性,人们提出了Unicode标准。Unicode对世界上大多数文本系统进行排列和编码,以便计算机能够以统一的方式处理文本。目前Unicode已经收集了超过14万个字符,自然支持多种语言。(Unicode的uni是“统一”的根源)

  

1 Unicode

  

2 Python中的Unicode

  Python 3以后,str对象在内部用Unicode表示,所以在源代码中变成了Unicode对象。使用Unicode的好处是程序的核心逻辑统一使用Unicode,在输入和输出层面只需要解码和编码,可以最大程度的避免各种编码问题。

  图示如下:

  

2.1 Unicode对象的好处

  问题:由于Unicode有14万多个字符,每个字符至少需要4个字节才能保存(这里应该是因为2个字节不够,所以只用4个字节,一般不用3个字节)。而英文字符用ASCII码表示只需要1个字节,常用英文字符用Unicode的话成本会是原来的4倍。

  首先,我们来看看Python中不同形式的str对象的大小差异:

  sys . get sizeof( ab )-sys . get sizeof( a )

  一个

  sys . get sizeof( one two )-sys . get sizeof( one )

  2

  sys . get sizeof( )-sys . get sizeof( )

  四

  所以Python对Unicode对象进行了优化:根据文本内容,选择底层存储单元。

  根据文本字符的Unicode码位范围,Unicode对象的基础存储分为三类:

  PyUnicode_1BYTE_KIND:所有字符的码位都在U 0000和U 00FF之间。PyUnicode_2BYTE_KIND:所有字符的码位都在U000和U FFFF之间,至少有一个字符的码位大于U00FFPyUnicode _ 1byte _ k

  IND:所有字符码位在U+0000到U+10FFFF之间,且至少有一个字符的码位大于U+FFFF

  对应枚举如下:

  

enum PyUnicode_Kind {

  /* String contains only wstr byte characters. This is only possible

   when the string was created with a legacy API and _PyUnicode_Ready()

   has not been called yet. */

   PyUnicode_WCHAR_KIND = 0,

  /* Return values of the PyUnicode_KIND() macro: */

   PyUnicode_1BYTE_KIND = 1,

   PyUnicode_2BYTE_KIND = 2,

   PyUnicode_4BYTE_KIND = 4

  };

  

  根据不同的分类,选择不同的存储单元:

  

/* Py_UCS4 and Py_UCS2 are typedefs for the respective

   unicode representations. */

  typedef uint32_t Py_UCS4;

  typedef uint16_t Py_UCS2;

  typedef uint8_t Py_UCS1;

  

  对应关系如下:

  文本类型字符存储单元字符存储单元大小(字节)PyUnicode_1BYTE_KINDPy_UCS11PyUnicode_2BYTE_KINDPy_UCS22PyUnicode_4BYTE_KINDPy_UCS44

  由于Unicode内部存储结构因文本类型而异,因此类型kind必须作为Unicode对象公共字段进行保存。Python内部定义了一些标志位,作为Unicode公共字段:(介于笔者水平有限,这里的字段在后续内容中不会全部介绍,大家后续可以自行了解。抱拳~)

  

  • interned:是否为interned机制维护
  • kind:类型,用于区分字符底层存储单元大小
  • compact:内存分配方式,对象与文本缓冲区是否分离
  • asscii:文本是否均为纯ASCII

  通过PyUnicode_New函数,根据文本字符数size以及最大字符maxchar初始化Unicode对象。该函数主要是根据maxchar为Unicode对象选择最紧凑的字符存储单元以及底层结构体:(源码比较长,这里就不列出了,大家可以自行了解,下面以表格形式展现)

  maxchar < 128128 <= maxchar < 256256 <= maxchar < 6553665536 <= maxchar < MAX_UNICODEkindPyUnicode_1BYTE_KINDPyUnicode_1BYTE_KINDPyUnicode_2BYTE_KINDPyUnicode_4BYTE_KINDascii1000字符存储单元大小(字节)1124底层结构体PyASCIIObjectPyCompactUnicodeObjectPyCompactUnicodeObjectPyCompactUnicodeObject

  

  

3 Unicode对象的底层结构体

  

  

3.1 PyASCIIObject

  C源码:

  

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 interned:2;

   unsigned int kind:3;

   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;

  

  源码分析:

  length:文本长度

  hash:文本哈希值

  state:Unicode对象标志位

  wstr:缓存C字符串的一个wchar_t指针,以\0结束(这里和我看的另一篇文章讲得不太一样,另一个描述是:ASCII文本紧接着位于PyASCIIObject结构体后面,我个人觉得现在的这种说法比较准确,毕竟源码结构体后面没有别的字段了)

  图示如下:

  (注意这里state字段后面有一个4字节大小的空洞,这是结构体字段内存对齐造成的现象,主要是为了优化内存访问效率)

  

  ASCII文本由wstr指向,以’abc’和空字符串对象’'为例:

  

  

  

  

3.2 PyCompactUnicodeObject

  如果文本不全是ASCII,Unicode对象底层便由PyCompactUnicodeObject结构体保存。C源码如下:

  

/* Non-ASCII strings allocated through PyUnicode_New use the

   PyCompactUnicodeObject structure. state.compact is set, and the data

   immediately follow the structure. */

  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;

  

  PyCompactUnicodeObject在PyASCIIObject的基础上增加了3个字段:

  utf8_length:文本UTF8编码长度

  utf8:文本UTF8编码形式,缓存以避免重复编码运算

  wstr_length:wstr的长度(这里所谓的长度没有找到很准确的说法,笔者也不太清楚怎么能打印出来,大家可以自行研究下)

  注意到,PyASCIIObject中并没有保存UTF8编码形式,这是因为ASCII本身就是合法的UTF8,这也是ASCII文本底层由PyASCIIObject保存的原因。

  结构图示:

  

  

  

3.3 PyUnicodeObject

  PyUnicodeObject则是Python中str对象的具体实现。C源码如下:

  

/* Strings allocated through PyUnicode_FromUnicode(NULL, len) use the

   PyUnicodeObject structure. The actual string data is initially in the wstr

   block, and copied into the data block using _PyUnicode_Ready. */

  typedef struct {

   PyCompactUnicodeObject _base;

   union {

   void *any;

   Py_UCS1 *latin1;

   Py_UCS2 *ucs2;

   Py_UCS4 *ucs4;

   } data; /* Canonical, smallest-form Unicode buffer */

  } PyUnicodeObject;

  

  

  

3.4 示例

  在日常开发时,要结合实际情况注意字符串拼接前后的内存大小差别:

  

>>> import sys

  >>> text = a * 1000

  >>> sys.getsizeof(text)

  1049

  >>> text +=

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • python语言基本语句用法总结大全,python语言基本语句用法总结怎么写
  • python语言基本语句用法总结大全,python语言基本语句用法总结怎么写,python语言基本语句用法总结
  • python是一种什么类型的计算机语言,python语言是一种什么类型的编程语言
  • Python的保留字符,python语言中的保留字
  • python的指数e怎么表示,指数函数在python语言中怎么表示
  • python语言合法的变量命名,在python中变量的命名要注意哪些问题
  • python变量命名可以用中文吗,下面哪一个不是python语言合法的变量命名
  • Python分词库,用python语言中文分词第三方库jieba对文件data
  • python中复数类型的实部和虚部都是浮点数,python语言中,复数类型中实数部分和虚数部分
  • 用python语言判断一个数是否为素数,Python判断是不是素数
  • python语句变量命名规则,python语言命名变量规则
  • 简述python语言程序的特点,以下关于python语言技术特点
  • matlab中for循环的用法例子,python语言for循环语句
  • Python主网站,python语言的官方网站
  • 用python开发的软件有哪些,哪些工具可以使用python语言开发软件
  • 留言与评论(共有 条评论)
       
    验证码: