Cheng Jun's Blog

卷卷不是笨蛋


  • Home
  • Archive
  • Categories
  • Tags
  •  

© 2025 Cheng Jun

Theme Typography by Makito

Proudly published with Hexo

《流畅的Python》学习笔记

Posted at 2025-05-22 Technical sharing  Python 进阶  Last_modified 2025-05-22

笔记注释

我会用不同颜色的笔在notability上面做笔记,其中:

  • 蓝色表示自己的理解,并不确定是完全正确的表达。
  • 红色表示提醒,是完全没有问题的标注。

第四部分 面向对象的惯用法

8 对象引用,可变性和垃圾回收

  1. 变量不是盒子,对象在赋值之前就创建了,所以在对变量赋值的过程中,实际上就是在给变量贴标签,顺理成章的可以给一个对象贴很多个标签,引申出别名的概念。
  2. 元组具有相对不可变性,所以浅复制对于可变对象会同时改变原件和副本,但是对于元组(不可变对象),只会应用在改变的部分。理解浅复制副本共享内部对象的引用。
  3. 深复制需要用到copy库的copy()和deepcopy()这两个方法。
  4. python唯一支持的参数传递模式是共享传参,函数内部的形参是实参的别名,从而函数可能会修改接收到的任何可变对象。
  5. 默认的实参值(在括号里面参数)应该不可变,如果是可变的实参,会导致在实例化的时候该参数被共享,下面是一个简单的例子。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Bus:
def __init__(self, passengers = []):
self.passengers = passengers
def pick(self, name):
self.passengers.append(name)
def drop(self, name):
self.passengers.remove(name)

t1 = Bus()
t1.passengers
Out[4]: []
Bus().passengers
Out[5]: []
t1.pick(['a','b'])
Bus().passengers
Out[7]: [['a', 'b']]
  1. 创建或者调用类,函数的时候,要思考调用方法是否会修改传入的参数。解决的办法一般是创建副本。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a = [1 ,2 , 3, 4]
b = list(a)
b.append(1)
a
Out[5]: [1, 2, 3, 4]
b
Out[6]: [1, 2, 3, 4, 1]
## 特别注意,浅复制对可变对象是复制的对象的引用
a = [1,(1, 2),[1, 2, 3]]
b = list(a)
b[2].append(4)
a
Out[10]: [1, (1, 2), [1, 2, 3, 4]]
b
Out[11]: [1, (1, 2), [1, 2, 3, 4]]
  1. 第八章看完,对于其中的弱引用,动态内存管理的理解还是不够,希望以后会理解的更加明白。

9 符合python风格的对象

  1. Unicode编码,计算机保存字符串,保存的是二进制,所以对于字符串,需要进行编码和解码的工作,python默认支持UTF-8这种可变长度编码。Unicode不同的实现方式,比如UTF-16,UTF-8,UTF-32本质上就是编码的字节数不一样。为了独立的表示字符,编码应该是要唯一的。
  2. 迭代器,生成器,和可迭代对象。
  • <generator object> 生成器:生成器不会一次存储所有的值,而是会在需要的时候一次生成一个值。有两种方法定义生成器:
    • 生成器函数 当一个函数包含yield时,他是一个生成器,通过next()或者通过for循环进行遍历查看值。
    • 生成器表达式 例子(i for i in range(1, 2, 3)),和列表推导式很像。[i for i in range(1, 2, 3)]
    • 生成器本身就是迭代器,对它调用iter()只是返回它自己。
  • <iterable> 可迭代对象,生成器是可迭代对象;大多数Python内置类型(如list、tuple)的 __iter__ 方法都返回新的迭代器对象,而不是自身。因为如果返回自身,那必须要实现一个迭代器。返回可迭代对象的优点是:
    • 符合Python惯例:可迭代对象和迭代器分离
    • 避免状态管理:不需要跟踪迭代位置
    • 支持多重迭代:可以同时进行多个独立的迭代
    • 代码简洁:不需要实现复杂的__next__(self)方法
  • <iterator> 迭代器 迭代器需要实现两个特殊方法(魔法方法)__iter__(self)和__next__(self)。其中__iter__(self)返回的是它本身。
  1. Python的format方法支持三种转换标志:!s - 调用 str() 函数(默认行为),!r - 调用 repr() 函数,!a - 调用 ascii() 函数。!r出现在类的 __repr__ 方法中,__repr__()被调用需要是对构造方法的准确表达。(repr是为了让编程的人看懂的,这样会保留准确的引号,转义符号等。)目的是:
  • 显示准确的数据类型:!r 会保留字符串的引号,数字的确切表示等。
  • 便于调试:repr() 的输出通常是”无歧义的”,能清楚看出数据的真实形态。
  • 代码重现性:理想情况下,repr() 的输出应该是可以用来重新创建对象的有效Python表达式。

Share 

 Previous post: 《C++ Primer Plus》学习笔记 Next post: 你必须掌握的zsh快捷键 

© 2025 Cheng Jun

Theme Typography by Makito

Proudly published with Hexo