Skip to content

Commit 88b7007

Browse files
committed
post: python post
1 parent 7757d9d commit 88b7007

30 files changed

+425
-126
lines changed

content/posts/2025-12-18_python-distilled-04.md

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ def remove_item(items: list, item) -> list:
6464
return [i for i in items if i != item]
6565
```
6666

67-
一个 subtype 子类通过 inheritance 定义,其携带有原始类的所有特性,增加或重定义方法。
68-
`isinstance(instance, type)` 函数是检查值与类型是否匹配的首选方法,因为它能够识别子类型,该函数还可以同时检查多种可能的类型。
67+
一个 subtype 子类通过 inheritance 定义,其携带有原始类的所有特性,可以增加或重定义方法。
68+
`isinstance(instance, type)` 函数是检查值与类型是否匹配的首选方法,因为它能够识别子类型。
69+
该函数还可以同时检查多种可能的类型。
6970

7071
```Python
7172
class mylist(list):
@@ -74,3 +75,126 @@ class mylist(list):
7475
if isinstance(items, (list, tuple)):
7576
maxval = max(items)
7677
```
78+
79+
尽管类型检查可以加入程序中,但类型检查往往没有想象中的那么好用。
80+
首先,过度的类型检查很影响性能。
81+
其次,程序并不总是定义成完美契合于一个良好的类型层次结构,比如 `isinstance(items, list)` 无法检测一个非继承自 list 但类 list 的类型。
82+
83+
## Reference Counting and Garbage Collection
84+
85+
Python 通过自动垃圾回收机制管理对象,所有对象都通过引用计数 reference counting。
86+
每当一个对象被分配一个新的名称,或放入一个新容器中后,就会增加引用计数,如下:
87+
88+
```python
89+
a = 37 # 创建对象 37
90+
b = a # 增加引用计数
91+
c = []
92+
c.append(b) # 增加引用计数
93+
```
94+
95+
对象的引用计数会因 `del` 语句或引用超出作用域而减少。
96+
可以使用 `sys.getrefcount()` 获取一个对象的引用计数:
97+
98+
```Python
99+
import sys
100+
101+
a = 37
102+
sys.getrefocunt(a)
103+
```
104+
105+
引用计数可能会比预计的大,这是因为解释器会在不同地方共享这种变量,以节约内存。
106+
由于这些变量不可变,因此往往不会被注意到。
107+
108+
> 注意
109+
110+
从 Python 3.12 [PEP 683](https://peps.python.org/pep-0683/) 开始引入了 Immoral Objects 永生对象,对于这类对象,其内部运行时状态将不再改变,引用计数永远不会减到 0,除了在解释器终止的时候。
111+
112+
使用新版对小数使用这个方法会得到一个非常大的值(2 的 32 次方减 1)。
113+
114+
```bash
115+
% python -c "import sys; print(sys.getrefcount(37))"
116+
4294967295 # 2^(32) - 1
117+
```
118+
119+
当对象的引用计数到 0 后会被垃圾回收。
120+
然而,在某些情况下,一组不再使用的对象之间可能存在循环依赖。
121+
122+
```Python
123+
a = { }
124+
b = { }
125+
a['b'] = b
126+
b['a'] = a
127+
del a
128+
del b
129+
```
130+
131+
在这个例子中,del 语句将 a 和 b 的引用计数减少,并摧毁引用的名称。
132+
但由于互相引用,引用计数无法变成 0,也就无法释放。
133+
最终,解释器不会发生内存泄露,但对象的消毁会延迟,直到循环检测器执行后找到并删除那些无法访问的对象。
134+
135+
随着解释器在执行过程中分配越来越多的内存,循环检测算法会定期运行。
136+
具体的行为可以使用 `gc` 标准库来微调和控制,`gc.collect()` 函数可以立即触发循环垃圾回收器。
137+
138+
在使用巨大的数据结构的时候,手动删除对象是合理的。
139+
140+
```Python
141+
def some_calculation():
142+
data = create_giant_data_structure()
143+
# Use data for some part of a calculation
144+
...
145+
146+
# Release the data
147+
del data
148+
149+
# Calculation continues
150+
...
151+
```
152+
153+
## References and Copies
154+
155+
等于号会创建一份引用,而不是复制一份对象
156+
157+
```Python
158+
a = [1, 2, 3]
159+
b = a
160+
b is a # True
161+
b[1] = -2
162+
a # [1, -2, 3]
163+
```
164+
165+
上面例子中,a 和 b 都指向同一个对象,因此修改 b 会导致 a 也被修改。
166+
167+
如果不希望拷贝引用,而是真实的赋值,有两种方法,浅拷贝和深拷贝。
168+
169+
```Python
170+
a = [1, 2, [3, 4]]
171+
b = list(a) # 创建一份浅拷贝
172+
b is a # False
173+
b.append(100)
174+
b # [1, 2, [3, 4], 100]
175+
a # [1, 2, [3, 4]]
176+
177+
b[2][0] = -100
178+
b # [1, 2, [-100, 4]]
179+
a # [1, 2, [-100, 4]]
180+
```
181+
182+
上面例子中,b 修改外层变量,a 没有改变,但修改内层变量 a 被改变了。
183+
184+
这是因为浅拷贝只会复制最外层的变量,对于嵌套的变量不会拷贝内层变量,使用深拷贝才会循环拷贝嵌套变量。
185+
并没有可以进行深拷贝的操作符,但是开使用 `copy.deepcopy()` 来实现。
186+
187+
```Python
188+
import copy
189+
190+
a = [1, 2, [3, 4]]
191+
b = copy.deepcopy(a)
192+
193+
b[2][0] = -100
194+
b # [1, 2, [-100, 4]]
195+
a # [1, 2, [3, 4]]
196+
```
197+
198+
不要在非必要的地方使用 deepcopy,因为速度很慢,同时要注意深拷贝无法拷贝系统或运行时状态(例如打开文件、网络连接、线程、生成器等)。
199+
200+
## Object Representation and Printing
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
+++
2+
date = '2025-12-23T8:00:00+08:00'
3+
draft = false
4+
title = 'Python PEP 683: Immoral Objects'
5+
tags = ['Python']
6+
+++
7+
8+
[PEP 683](https://peps.python.org/pep-0683/) 改变了 Python 原有引用计数的一些逻辑,下面简单介绍一下。
9+
10+
CPython 的“引用计数可变性”已经成为并发、性能和未来发展的系统性障碍。
11+
12+
---
13+
14+
引用对象导致 “逻辑不可变对象” ≠ “物理不可变对象”
15+
16+
在 Cpython 中
17+
18+
- `None`
19+
- `True/False`
20+
- `int`, `str`, `list` 等内建对象
21+
22+
在运行时引用计数会频繁变动,这意味着内存内容在不断被写入,在底层并非真正的 immutable
23+
24+
---
25+
26+
引用计数写操作降低并发性能
27+
28+
- CPU Cache Line 失效
29+
30+
`Py_INCREF / Py_DECREF` 会写内存 -> cache line invalidation
31+
32+
在多线程 / 多核环境中,同一个全局对象被频繁引用,会造成严重的缓存抖动
33+
34+
- fork + Copy-on-Write 失效
35+
36+
父子进程共享内存页
37+
38+
只要引用计数一变 -> 页面被写 -> 触发 COW
39+
40+
只是“多拿了个引用”,却导致整页内存复制
41+
42+
---
43+
44+
为 free-threading (no GIL) 清扫道路
45+
46+
CPython 的引用计数本质是全局共享的可变状态,在无 GIL 下会产生高频数据竞争。
47+
要么给 refcount 加锁(性能太差),要么让一部分的 refcount 不再变化。
48+
49+
该提案将“对象生命周期模型”划分成了两类对象
50+
51+
| 对象类型 | 生命周期 | refcount 行为 |
52+
| :------- | :------- | :-------------- |
53+
| 普通对象 | 动态 | 正常增减 |
54+
| 不朽对象 | 解释器级 | 固定,不参与 gc |
55+
56+
这让后续优化和推理都更清晰,也会导致 `sys.getrefcount()` 不再具有语义价值,测试默认返回 2 的 23 次方减 1。

public/archives/index.html

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,13 @@
5151
<span class="max-w-[4rem] md:max-w-none truncate">Home</span></a></li><li class="flex items-center gap-1 md:gap-2 min-w-0"><span class="text-muted-foreground/50 flex-shrink-0"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
5252
</span><span class="text-foreground flex items-center gap-0.5 md:gap-1 font-medium min-w-0 flex-shrink-0"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"/></svg>
5353
<span class="max-w-[3rem] md:max-w-none truncate">Archives</span></span></li></ol></nav><header class=mb-8><div class="mb-4 flex items-center gap-3"><svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"/></svg><h1 class="text-foreground text-3xl font-bold">Archives</h1></div><p class="text-muted-foreground mb-6">Browse all articles in chronological order and discover what interests you.</p><div class="text-muted-foreground flex items-center gap-4 text-sm"><div class="flex items-center gap-1"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg>
54-
<span>89 posts total</span></div><div class="flex items-center gap-1"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>
55-
<span>Timeline view</span></div></div></header><div class=relative><div class="bg-border absolute top-0 bottom-0 left-4 w-0.5"></div><div class=mb-12><div class="relative mb-8 flex items-center"><div class="bg-primary absolute left-0 z-10 flex h-8 w-8 items-center justify-center rounded-full"><svg class="h-4 w-4 text-primary-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg></div><div class=ml-12><h2 class="text-foreground text-2xl font-bold">2025</h2><p class="text-muted-foreground text-sm">87
56-
posts</p></div></div><div class="relative mb-8"><div class="relative mb-4 flex items-center"><div class="bg-accent border-background absolute left-2 z-10 h-4 w-4 rounded-full border-2"></div><div class=ml-12><h3 class="text-foreground text-lg font-semibold">December 2025</h3><p class="text-muted-foreground text-xs">7
57-
posts</p></div></div><div class="ml-12 space-y-3"><article class="group bg-card border-border hover:bg-accent/50 rounded-lg border p-4 transition-all duration-300"><div class="flex items-center justify-between gap-4"><div class="min-w-0 flex-1"><h4 class="text-foreground group-hover:text-primary mb-3 font-medium transition-colors duration-200"><a href=/posts/shell/ class=block>Shell</a></h4><div class="text-muted-foreground flex items-center gap-4 text-xs"><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>
54+
<span>90 posts total</span></div><div class="flex items-center gap-1"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>
55+
<span>Timeline view</span></div></div></header><div class=relative><div class="bg-border absolute top-0 bottom-0 left-4 w-0.5"></div><div class=mb-12><div class="relative mb-8 flex items-center"><div class="bg-primary absolute left-0 z-10 flex h-8 w-8 items-center justify-center rounded-full"><svg class="h-4 w-4 text-primary-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg></div><div class=ml-12><h2 class="text-foreground text-2xl font-bold">2025</h2><p class="text-muted-foreground text-sm">88
56+
posts</p></div></div><div class="relative mb-8"><div class="relative mb-4 flex items-center"><div class="bg-accent border-background absolute left-2 z-10 h-4 w-4 rounded-full border-2"></div><div class=ml-12><h3 class="text-foreground text-lg font-semibold">December 2025</h3><p class="text-muted-foreground text-xs">8
57+
posts</p></div></div><div class="ml-12 space-y-3"><article class="group bg-card border-border hover:bg-accent/50 rounded-lg border p-4 transition-all duration-300"><div class="flex items-center justify-between gap-4"><div class="min-w-0 flex-1"><h4 class="text-foreground group-hover:text-primary mb-3 font-medium transition-colors duration-200"><a href=/posts/python-pep-683-immoral-objects/ class=block>Python PEP 683: Immoral Objects</a></h4><div class="text-muted-foreground flex items-center gap-4 text-xs"><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>
58+
<time datetime=2025-12-23>12-23</time></div><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3A9 9 0 113 12a9 9 0 0118 0z"/></svg>
59+
<span>1
60+
min</span></div></div></div></div></article><article class="group bg-card border-border hover:bg-accent/50 rounded-lg border p-4 transition-all duration-300"><div class="flex items-center justify-between gap-4"><div class="min-w-0 flex-1"><h4 class="text-foreground group-hover:text-primary mb-3 font-medium transition-colors duration-200"><a href=/posts/shell/ class=block>Shell</a></h4><div class="text-muted-foreground flex items-center gap-4 text-xs"><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>
5861
<time datetime=2025-12-18>12-18</time></div><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3A9 9 0 113 12a9 9 0 0118 0z"/></svg>
5962
<span>9
6063
min</span></div></div></div></div></article><article class="group bg-card border-border hover:bg-accent/50 rounded-lg border p-4 transition-all duration-300"><div class="flex items-center justify-between gap-4"><div class="min-w-0 flex-1"><h4 class="text-foreground group-hover:text-primary mb-3 font-medium transition-colors duration-200"><a href=/posts/python-tricks-part-3-program-structure-and-control-flow/ class=block>Python Tricks Part 3: Program Structure and Control Flow</a></h4><div class="text-muted-foreground flex items-center gap-4 text-xs"><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>

public/en/sitemap.xml

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)