Python Tricks Part 4: Objects, Types and Protocols

Essential Concepts 每个存储在程序中的数据都是一个对象,每个对象都有一个 identity, type and value (身份、类型和值)。 例如 a = 42 会创建一个整数为 42 的类型,该对象的 identity 是内存中的一个数字,代表其在内存中的位置,a 是这个类的标签,指向这个特定的内存位置,标签本身并非对象的一部分。 object 对象的类型,也被称为 class 类,该类定义了对象的内部数据表示,和支持的方法。 当特定类型的对象创建后,该对象被称为该类的 instance “实例”。 当实例创建后,其 identity 就不会改变。 如果一个对象的值可以被修改,则该对象是可变的 mutable。 如果一个对象的值不可以被修改,则该对象是不可变的 unmutable。 一个持有对其他对象引用的对象,被称为容器。 对象通过其属性来表征,属性是于对象关联的值,通过点 . 运算符来访问。 属性可以是一个简单的值,例如一个数字,也可以是一个被调用以执行某些操作的函数。 这类函数被称为方法,例如下面这个例子 a = 34 # Create an integer n = a.number # Get the numberator (an attribute) b = [1, 2, 3] # Create a list b.append(4) # Add a new element using the append method Object Identity and Type 内置函数 id() 返回对象的 identity,该 identity 是一个整数,通常对应 object 的内存地址。 is 操作符会对比两个对象的 identity,type() 返回对象的类型。 ...

December 18, 2025 · 9 min · 1715 words · Starslayerx

Shell

Terminal 终端是提供文本用户界面的程序,早期终端是集成设备,键盘和屏幕集成在一起,现在终端知识简单的应用程序。 除了基本的输入输出外,终端还支持将所谓转义序列或转移码,用于光标和屏幕处理,并可能支持颜色。 例如,使用 Ctrl-h 会删除前面一个字符。 环境变量 TERM 可能使用了终端模拟器,其配置可以通过 infocmp 获得 # Reconstructed via infocmp from file: /usr/share/terminfo/74/tmux-256color tmux-256color|tmux with 256 colors, am, hs, km, mir, msgr, xenl, colors#256, cols#80, it#8, lines#24, pairs#32767, acsc=++\,\,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, civis=\E[?25l, clear=\E[H\E[J, cnorm=\E[34h\E[?25h, cr=^M, ... 显示内容看上去很混乱,这些是 Shell shell 是一个运行在终端内部的程序,充当命令解释器。 shell 通过流提供输入和输出处理,支持变量,有一些内置命令,处理命令执行和状态,支持交互式和脚本使用。 最初的 shell 叫做 Bourne shell sh,即作者名字命名,现在通常被 bash 替代,即 “Bourne Again Shell” 的缩写。 file -h /bin/sh Stream shell 为每个进程提供了三个默认的文件描述符 (FD),用于输入和输出: ...

December 18, 2025 · 5 min · 995 words · Starslayerx

Python Tricks Part 3: Program Structure and Control Flow

Exceptions 异常 exceptions 具有一些标准属性,这些属性在需要针对错误执行进一步操作的代码中可能非常有用。 e.args 这是引发异常时提供的元组,在大多数情况下,这是一个包含描述错误字符串的单元元素元组。 对于 OSError 异常,其值是一个包含整数错误码、字符串错误消息,以及可选文件名的 2 元组或 3 元组。 e.__cause__ 如果该异常是在处理另一个异常时有意引起的 raise ... from ...,Python 会将这两个异常链接起来,形成异常链。 e.__context__ 如果异常是处理异常时无意间导致的,则会产生 e.__context__。 e.__traceback__ 与异常相关联的堆栈回溯对象。 用于存储异常值的变量仅在相关的 except 块内部可以访问,一但控制论离开该块,该变量将变为未定义。 try: int('N/A') except ValueError as e: print('Failed:', e) print(e) # Fails -> NameError. 'e' not defined 多异常处理块通过多个异常子句指定: try: # do something except TypeError as e: # Handle Type error except ValueError as e: # Handle Value error 当然也可以在单个子句中处理多个异常类型 try: # do something except (TypeError, ValueError) as e: # Handle Type or Value error 可以使用 pass 忽略报错 ...

December 17, 2025 · 7 min · 1335 words · Starslayerx

Python Tricks Part 2: Operators, Expressions and Data Manipulation

Literals 整数 04 0b101010 # Binary 二进制 0o52 # Octal 八进制 0x2a # Hexadecimal 十六进制 浮点数,内部使用 IEEE 754 双精度存储 4.2 42. 4.2e+2 # 科学记数法 4.2E2 -4.2e-2 数字类型字面量还可以使用 _ 来方便阅读 123_456_789 Truth Values true: 非0数字、任何非空的字符串,列表,元组或字典 false: 0、None、空列表,元组或字典 Operations Involving Iterables 任何可迭代对象都可以展开,如 list, tuple and set,都通过星号(*)。 items = [1, 2, 3] a = [10, *items, 1] # [10, 1, 2, 3, 1] b = (*items, 10, *items) # [1, 2, 3, 10, 1, 2, 3] c = {10, 11, *items} # {10, 11, 1, 2, 3} 在上面例子中,item 简单的被粘贴到 list, tuple, set 中,就和手动输入进去一样。 有时候这种展开 expansion 被称为“展开操作符” splatting。 ...

December 16, 2025 · 2 min · 328 words · Starslayerx

Python Tricks Part 1: Basis

这篇文章总结一些平时容易被忽略的 Python 知识 Primitives, Variables and Expressions print(f"{year:>3d} {principal:0.2f}") >3d 指至少 3 位十进制数,右对齐 0.2f 指精度为 2 位的浮点数 Arithmetic Operators round(x, [n]): 该函数采用 Banker’s Rounding 银行家舍入法,也叫 四舍六入五成双,当要舍弃的数字正好是 5 时 前一位是偶数 → 向下舍去(向偶数靠拢) 如果前一位是奇数 → 向上进位(向偶数靠拢) 这样做的目的是减少舍入误差的累积,在统计学和金融计算中更为公平。 # 常规四舍五入(Python实际行为是银行家舍入) print(round(1.5)) # 2 (1是奇数,5进位) print(round(2.5)) # 2 (2是偶数,5舍去) print(round(3.5)) # 4 (3是奇数,5进位) print(round(4.5)) # 4 (4是偶数,5舍去) # 更复杂的例子 print(round(1.25, 1)) # 1.2 (2是偶数,5舍去) print(round(1.35, 1)) # 1.4 (3是奇数,5进位) print(round(1.251, 1)) # 1.3 (因为后面还有1,不是正好5,正常进位) 银行家舍入法是 IEEE 754 标准推荐的方式,Python、R、NumPy 等都采用这种舍入方式,能有效减少大量数据计算时的统计偏差。 Python 二进制运算符会将整数视为 2’s complement binary representation 二进制补码,并且符号位会在左侧无限扩展。 此外,Python 不会截断二进制,也不会溢出。 ...

December 15, 2025 · 4 min · 662 words · Starslayerx

Python asyncio 03: A first asyncio application

Working with blocking sockets socket 是在网络中读取和写入数据的一种方式。 可以将 socket 看成一个邮件,将信封放到里面后运送到接收者的地址。 下面使用 Python 的内置 socket 模块来创建一个简单的 server import socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 这里,给 socket 函数指定了两个参数,第一个是 socket.AF_INET,这个告诉我们要与什么类型的地址进行交互,在这个例子中是 hostname 和 phonenumber。 第二个是 socket.SO_REUSEADDR,这个参数是说我们使用 TCP 协议进行交互。 然后使用 socket.setsockopt 方法将 socket.SOL_SOCKET 标志设置为 1。这将允许在关闭和快速重启应用,避免 address already in use 这类错误,如果不这样做将会消耗操作系统一段时间来解除与 port 的绑定。 使用 socket.socket 创建 socket 后,并不能开始沟通,因为还没有将其绑定到任何地址上面。 在本例中,将使用电脑本地地址 127.0.0.1 和任意 port 8000 server_address = ('127.0.0.1', 8000) server_socket.bind(server_address) 这里将地址设置为 127.0.0.1:8000,这意味着 client 将能够使用该地址向服务器发送数据,如果要向 client 发送数据,也会看到该地址为来源地址。 接下来,在套接字上调用 listen 方法,主动监听来自客户端的连接请求。 随后,通过调用 accept 方法等待连接建立。 该方法会保持阻塞状态直至接收到连接请求,当连接成功时,将返回一个连接对象及客户端地址。 这个连接对象本质上是一个新的套接字,可以用于与客户端进行双向数据通信 server_socket.listen() connection, client_address = server_socket.accept() 有了这些组件,我们便掌握了创建基于套接字的服务器应用所需的所有基础模块。 该应用将等待连接,并在建立连接后打印提示信息。 ...

December 1, 2025 · 10 min · 1975 words · Starslayerx

Python Asyncio 02: Asyncio Basics Part 2

Tasks, coroutines, furtures, and awaitables Coroutines 和 tasks 都是 await 表达式,那他们的相同线程是哪个? 下面介绍 future 也被称作 awaitable,理解 futures 是理解 asyncio 内部工作的重点。 Introducing futures Future 代表一个尚未完成的异步操作的最终结果。 from asyncio import Future my_future = Future() print(f"Is my_future done? {my_future.done()}") my_future.set_result(42) print(f"Is my_future done? {my_future.done()}") print(f"What is the result of my_future? {my_future.result()}") 输出为 Is my_future done? False Is my_future done? True What is the result of my_future? 42 使用构造器 Future 来创建 future,这时 future 没有值,因此调用 done 结果是 False。 然后使用 set_result 设置值,这将 future 标记为 done。 相似的,如果想要在 future 中设置异常,使用 set_exception 方法。 ...

November 21, 2025 · 5 min · 1049 words · Starslayerx

Python Asyncio 02: Asyncio Basics Part 1

Introducing coroutines 创建一个协程 coroutine 而不是创建一个函数类型,使用 async def 关键字,而不是 def: async def coroutine_add_one(number: int) -> int: return number + 1 def add_one(number: int) -> int: return number + 1 function_result = add_one(1) coroutine_result = coroutine_add_one(1) print(f"Function result is {function_result} and the type is {type(function_result)}") print(f"Coroutine result is {coroutine_result} and the type is {type(coroutine_result)}") 输出如下 Function result is 2 and the type is <class 'int'> Coroutine result is <coroutine object coroutine_add_one at 0x103000a00> and the type is <class 'coroutine'> 可以看到,协程返回的不是值,而是一个协程对象。 这里协程并没有执行,而是创建了一个协程对象可在之后运行,要运行一个协程则必须显式地在一个事件循环中运行它。 在 Python 3.7 之后的版本,必须创建事件循环来运行它。 asyncio 库添加了多个函数,抽象了事件循环的管理,例如 asyncio.run(),可以使用它来运行协程: ...

November 20, 2025 · 3 min · 637 words · Starslayerx

Python Asyncio 01: Getting to know asyncio

Python asyncio 基础篇 本篇包含 asyncio 是什么以及如何使用它 concurrency 并发、parallelism 并行、threads 线程和 processes 进程 GIL (global interpreter lock) 全局解释器锁和其带来的并发跳转 非阻塞 sockets 如何只通过一个线程实现并发 基于事件循环 (event-loop-based) 并发的基本原理 异步编程 (asynchronous programming) 意思是可以在主程序之外,额外运行一个特定的长时运行的任务。 一个 coroutine 协程是一种方法,协程是一种方法,当遇到可能长时间运行的任务时,它可以暂停执行,并在任务完成后恢复执行。 asyncio 这个库的名称可能让人人为其只适合编写 I/O 操作,但实际上该库可以和 threading 和 multiprocessing 库结合使用。 基于这种 interoperability 互操作性,可以使用 async/await 关键字让工作流更加容易理解。 这意味着,asyncio 不仅适合 I/O 的并发,也可以在 CPU 密集操作中使用。 所谓的 I/O-bound 和 CPU-bound 是指限制程序运行更快的主要因素,这意味着如果增加该方面的性能,程序就能够在更短的时间内完成。 下面是一些例子 I/O 密集操作:网络请求、文件读取 CPU 密集操作:循环遍历文件夹、计算 pi import requests response = requests.get('https://www.example.com') # 1 items = response.headers.items() headers = [f'{key}: {headers}' for key, header in items] # 2 formatted_headers = '\n'.join(headers) # 3 with open('headers.txt', 'w') as file: # 4 file.write(formatted_headers) I/O-bound 网络请求 CPU-bound 响应处理 CPU-bound 字符串拼接 I/O-bound 写入磁盘 Concurrency 并发 和 Parallelism 并行的区别这里就不多说了。 ...

November 19, 2025 · 3 min · 587 words · Starslayerx

Postgresql 03: psql Tool Introduction

psql 介绍 psql 是 PostgreSQL 中的一个交互式命令行工具,类似 Oracle 的 sqlplus,它允许用户交互式输入 SQL 语句或命令,然后发送给 PostgreSQL 服务器,再显示结果。 此外,psql 还有大量类似 shell 的特性来编写脚本,实现自动化操作。 在安装 postgresql 的时候,会创建一个与初始化数据库时的操作系统同名的数据库用户,这个用户是这个数据库的超级用户。 因此,在 OS 用户下登陆数据库时,会执行操作系统认证,因此无需用户名和密码,也可以通过修改 pg_hba.conf 文件来要求用户输入密码。 psql 也支持使用命令行参数来查询信息和执行 SQL,这种非交互模式与 linux 命令就没有太大区别了。 例如使用 psql -l 查看数据库,当然也可以通过命令进入数据库后,输出 \l 命令查看有哪些数据库。 默认会有一个叫 postgres 的数据库,这是默认安装后就有的一个数据库。 还有两个模板数据库,template0 和 template1。 当用户创建创建数据库时,是从模板数据库 template1 克隆来的,因此通常可以订制 template1 中的内容,例如添加一些表和函数,这样后续创建的数据库也会有这些表和函数。 template0 是一个最简化的数据库,如果指明从此数据库克隆,将创建出一个最简化的数据库。 使用 \d 查看有哪些表,使用 \c 连接到某数据库。连接命令格式如下: psql -h <hostname or ip> -p <port> [数据库名称] [用户名称] 也可以通过环境变量指定 export PGDATABASE=db_name export PGHOST=ip export PGPORT=port export PGUSER=postgres psql 常用命令 \h 命令查询 SQL 语法 ...

November 17, 2025 · 2 min · 254 words · Starslayerx