Python 中的数据类型

基本数据类型的底层实现

1. 整数 (int)

语法:

x = 10
y = -5
z = 0
large_num = 1_000_000  # 使用下划线提高可读性

底层实现:

  • Python 3 的 int 是任意精度整数
  • 使用 C 语言的 PyLongObject 结构体
  • 内部使用数字数组表示大整数
  • 小整数 (-5 到 256) 有缓存机制
# 底层结构示意
class PyLongObject:
    ob_refcnt    # 引用计数
    ob_type      # 类型指针
    ob_size      # 数字的位数(绝对值)
    ob_digit[0]  # 数字数组(实际存储)

内存布局:

小整数: 直接存储在对象头中
大整数: 对象头 + 动态分配的数字数组

2. 浮点数 (float)

语法:

a = 3.14
b = -2.5
c = 1.0
scientific = 1.23e-4  # 科学计数法

底层实现:

  • 基于 C 语言的 double 类型(双精度浮点数)
  • 使用 IEEE 754 标准
  • 64位表示:1位符号 + 11位指数 + 52位尾数
# 浮点数精度问题(所有语言通用)
print(0.1 + 0.2 == 0.3)  # False
print(0.1 + 0.2)         # 0.30000000000000004

3. 布尔值 (bool)

语法:

is_valid = True
is_done = False

底层实现:

  • 实际上是 int 的子类
  • True == 1, False == 0
  • 单例模式,只有两个实例
print(issubclass(bool, int))  # True
print(True + 1)               # 2
print(False * 5)              # 0

4. 字符串 (str)

语法:

s1 = "hello"
s2 = 'world'
s3 = """多行
字符串"""
s4 = r"原始字符串\n不转义"  # raw string

底层实现:

  • Python 3 使用 Unicode (UTF-8) 编码
  • 内部结构优化:
  • 紧凑字符串(Python 3.3+)
  • 字符串驻留(小字符串缓存)
// C 底层结构
typedef struct {
    PyObject_HEAD
    Py_ssize_t length;          // 字符串长度
    Py_hash_t hash;             // 缓存哈希值
    struct {
        unsigned int interned:2; // 驻留状态
        unsigned int kind:3;     // 字符宽度(1,2,4字节)
        unsigned int compact:1;  // 紧凑标志
        unsigned int ascii:1;    // ASCII 标志
        unsigned int ready:1;    // 就绪标志
    } state;
    wchar_t *wstr;              // 宽字符表示
} PyUnicodeObject;

容器类型的底层实现

1. 列表 (list)

语法:

lst = [1, 2, 3, "hello"]
lst.append(4)
lst[0] = 10

底层实现:

  • 动态数组(可扩容的指针数组)
  • 过度分配策略:分配比实际需要更多的空间
// C 底层结构
typedef struct {
    PyObject_VAR_HEAD
    PyObject **ob_item;        // 指向元素指针数组的指针
    Py_ssize_t allocated;      // 已分配的空间数量
} PyListObject;

内存增长策略:

# 扩容公式:new_allocated = (size + (size >> 3) + 6) & ~3
# 示例增长序列:0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...

2. 元组 (tuple)

语法:

tup = (1, 2, 3, "hello")
single = (42,)  # 单元素元组需要逗号

底层实现:

  • 固定大小的数组
  • 比列表更节省内存(无过度分配)
  • 小元组缓存机制
// C 底层结构
typedef struct {
    PyObject_VAR_HEAD
    PyObject *ob_item[1];      // 柔性数组成员
} PyTupleObject;

3. 字典 (dict)

语法:

d = {"name": "Alice", "age": 30}
d["city"] = "New York"

底层实现:

  • 哈希表(开放定址法)
  • Python 3.6+ 保持插入顺序
  • 结合稀疏表和紧凑表
// C 底层结构(简化)
typedef struct {
    Py_ssize_t me_hash;        // 键的哈希值缓存
    PyObject *me_key;          // 键
    PyObject *me_value;        // 值
} PyDictKeyEntry;

typedef struct _dictkeysobject {
    Py_ssize_t dk_refcnt;
    Py_ssize_t dk_size;        // 哈希表大小
    Py_ssize_t dk_usable;      // 可用条目数
    Py_ssize_t dk_nentries;    // 已用条目数
    PyDictKeyEntry dk_entries[1]; // 条目数组
} PyDictKeysObject;

哈希表解决冲突:

# 探测序列:index = hash(key) & mask
# 如果冲突:index = (5 * index + 1 + perturb) & mask

4. 集合 (set)

语法:

s = {1, 2, 3, 4}
s.add(5)

底层实现:

  • 基于字典实现,只有键没有值
  • 使用相同的哈希表机制
// C 底层结构
typedef struct {
    PyObject_HEAD
    PyObject *weakreflist;
    Py_ssize_t fill;           // 活跃 + 假删除条目数
    Py_ssize_t used;           // 活跃条目数
    Py_ssize_t mask;           // 掩码 = 表大小 - 1
    setentry *table;           // 哈希表
    Py_ssize_t finger;         // 搜索指纹
    setentry smalltable[8];    // 小集合优化
    Py_hash_t hash;            // 仅用于冻结集合
    Py_ssize_t num_active;     // 仅用于冻结集合
} PySetObject;

内存管理和优化

1. 小对象缓存

# 小整数缓存 (-5 到 256)
a = 100
b = 100
print(a is b)  # True - 同一个对象

# 字符串驻留
s1 = "hello"
s2 = "hello"
print(s1 is s2)  # True - 同一个对象

# 空元组单例
t1 = ()
t2 = ()
print(t1 is t2)  # True

2. 对象头开销

每个 Python 对象都有对象头:

typedef struct _object {
    Py_ssize_t ob_refcnt;    // 引用计数(8字节)
    PyTypeObject *ob_type;   // 类型指针(8字节)
} PyObject;

各种类型的内存占用:

import sys

print(f"int: {sys.getsizeof(0)} bytes")        # 24 bytes
print(f"float: {sys.getsizeof(0.0)} bytes")    # 24 bytes  
print(f"bool: {sys.getsizeof(True)} bytes")    # 24 bytes
print(f"空列表: {sys.getsizeof([])} bytes")    # 56 bytes
print(f"空字典: {sys.getsizeof({{}})} bytes")  # 64 bytes

3. 可变 vs 不可变类型

不可变类型: int, float, bool, str, tuple, frozenset

  • 创建后不能修改
  • 可哈希,可作为字典键
  • 线程安全

可变类型: list, dict, set, bytearray

  • 创建后可修改
  • 不可哈希,不能作为字典键
  • 线程不安全

性能特点总结

类型时间复杂度空间效率使用场景
listO(1) 索引,O(n) 插入删除中等有序集合,频繁索引
tupleO(1) 索引固定数据,字典键
dictO(1) 查找插入删除键值映射,快速查找
setO(1) 查找插入删除去重,成员测试
strO(1) 索引,O(n) 拼接文本处理
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇