Python函数框架:外框架、内框架与环境模型
一、引言当你在 Python 中调用一个函数时,解释器在背后做了大量工作来管理变量的"可见性"。为什么函数内部能访问全局变量,但全局却不能直接看到函数内部的变量?为什么嵌套函数能记住外层函数的变量?这一切的答案,都指向一个核心概念——环境模型(Environment Model)。 本文源自 UC Berkeley CS61A 课程的核心内容,带你从"框架(Frame)"的视角理解 Python 的函数调用机制。 二、什么是环境模型环境模型是 Python 解释器用来追踪变量名与值之间绑定关系的一套机制。它的核心思想极其简单: 一个表达式在特定环境中被求值。环境由一系列框架(Frame)组成,每个框架包含一组绑定(Binding)——即变量名到值的映射。 在这套模型中,有两种最关键的结构: 全局框架(Global Frame):程序启动时就存在的唯一框架,存储全局变量和函数定义 局部框架(Local Frame):每次函数调用时动态创建的新框架,存储函数的形参和局部变量 三、框架是什么框架本质上是一个上下文(Context),记录着...
Python如何像C++引用头文件
一、引言在C++中,我们通过#include指令引用头文件来复用代码,这种方式使得代码结构更加清晰,便于维护和管理。而在Python中,虽然没有直接的"头文件"概念,但通过其强大的模块导入系统,我们同样可以实现类似的代码组织和复用功能。本文将详细介绍Python中如何像C++引用头文件一样组织和导入代码。 二、C++头文件与Python模块的对比2.1 C++的头文件机制在C++中,头文件(.h文件)通常包含: 函数声明 类定义 常量定义 模板声明 通过#include指令,我们可以在源文件中引用这些头文件,从而使用其中定义的内容。 2.2 Python的模块机制在Python中,模块是一个包含Python定义和语句的文件,文件名就是模块名加上.py后缀。通过import语句,我们可以在其他Python文件中导入并使用模块中的内容。 三、Python模块的基本使用3.1 创建模块创建一个Python模块非常简单,只需要创建一个.py文件并在其中定义函数、类、变量等。 例如,创建一个名为utils.py的模块: 1234567891011# utils.py...
图形计算程序
引言在传统的 C++ 面向对象设计中,我们通常使用虚函数实现多态。本文将展示如何使用std::function替代虚函数,并结合移动语义,构建一个更灵活高效的图形计算程序。这种方式不仅能保持多态性,还能提升性能并增加代码灵活性。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631...
C++ 文件读取再整理
一、文件读取核心概念与基础流程1.1 文件操作的三要素文件读取本质是 "数据在外部存储与内存间的传输过程",需关注三个核心要素: 流对象:C++ 标准库通过std::ifstream(输入文件流)提供文件读取接口,是连接程序与外部文件的桥梁 流状态:通过good()/eof()/fail()/bad()四个状态标志判断操作有效性 数据缓冲区:操作系统与标准库均会维护缓冲区,减少磁盘 IO 次数(默认缓冲区大小通常为 4KB 或 8KB) 1.2 基础文件读取流程(标准范式)所有文件读取操作都遵循 "打开 - 读取 - 关闭" 的核心流程,标准实现代码如下: 123456789101112131415161718192021222324252627282930313233343536373839#include <fstream>#include <iostream>#include <string>int main() { // 1. 创建流对象并打...
Python 生成器和迭代器深度解析
一、什么是迭代器?迭代器(Iterator)是 Python 中一种实现了迭代协议的对象,它允许我们逐个访问集合中的元素,而不需要知道集合的内部结构。迭代器必须实现两个方法: __iter__():返回迭代器对象本身 __next__():返回下一个元素,如果没有更多元素则抛出 StopIteration 异常 1.1 迭代器的基本使用123456789101112# 创建一个迭代器numbers = [1, 2, 3, 4, 5]iterator = iter(numbers)# 使用 next() 函数获取下一个元素print(next(iterator)) # 输出: 1print(next(iterator)) # 输出: 2print(next(iterator)) # 输出: 3# 使用 for 循环遍历(自动处理 StopIteration 异常)for num in iterator: print(num) # 输出: 4, 5 1.2 自定义迭代器1234567891011121314151617class Countdown: def...
C++ 中 std::bind 与 std::function
一、std::function —— 可调用对象的 "万能容器"1.1 概念解析:什么是 std::function?std::function 是 C++11 标准库 头文件中引入的通用可调用对象封装器,其核心作用是将各种不同类型的可调用实体(函数指针、成员函数指针、lambda 表达式、函数对象)统一到一个类型安全的容器中。 可以将其类比为 "函数的通用接口转换器"—— 无论原始可调用对象的类型如何,只要签名(返回值类型 + 参数类型列表)匹配,就能被 std::function 封装并统一调用。 1.2 实现原理:类型擦除(Type Erasure)std::function 本质是通过类型擦除技术实现的多态封装,核心流程如下: 定义一个抽象基类(如 function_base),包含纯虚函数 operator()(对应目标签名)和析构函数; 为每个具体的可调用对象类型,实现一个模板派生类(如 function_impl),继承自 function_base,并在 operator() 中调用具体对象; std::functi...
Python 列表推导式深度解析
一、什么是列表推导式?列表推导式(List Comprehension)是 Python 中一种简洁、优雅的语法特性,用于快速创建列表。它允许我们在一行代码中完成对序列的迭代、过滤和转换操作,相比传统的 for 循环,代码更加简洁易读。 二、基本语法列表推导式的基本语法如下: 1[表达式 for 变量 in 可迭代对象 if 条件] 表达式:对每个元素执行的操作,结果将作为新列表的元素 变量:从可迭代对象中取出的每个元素 可迭代对象:可以是列表、元组、字符串、range 等 条件(可选):过滤条件,只有满足条件的元素才会被处理 三、基础用法3.1 简单列表生成123456789101112# 生成 0-9 的平方列表squares = [x ** 2 for x in range(10)]print(squares) # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]# 生成 1-10 的偶数列表evens = [x for x in range(1, 11) if x % 2 == 0]print(evens) # 输出: [2, 4...
Python 解包操作:* 和 ** 深度解析
一、 什么是解包操作?解包(Unpacking)是 Python 中一种强大的语法特性,它允许我们将容器类型(如列表、元组、字典等)中的元素“解压”出来,分别赋值给多个变量。Python 提供了两种主要的解包操作符: *:用于序列解包(列表、元组、字符串等可迭代对象) **:用于字典解包(将键值对解包为关键字参数) 二、 基础解包:无需操作符的简单情况在学习 * 和 ** 之前,我们先了解一下最基本的解包操作: 123456789101112131415# 基本解包 - 左右两边元素数量必须匹配name, age, city = ["Alice", 30, "New York"]print(name) # 输出: Aliceprint(age) # 输出: 30print(city) # 输出: New York# 元组解包同样适用coordinates = (10.5, 20.7)x, y = coordinatesprint(x, y) # 输出: 10.5 20.7# 字符串解包word = "abc"...
Python PIL库使用指南
一、什么是PIL?PIL(Python Imaging Library)是Python中最常用的图像处理库,它提供了丰富的图像处理功能,如打开、保存、调整大小、裁剪、旋转、滤镜等。PIL已经被Pillow库所取代,Pillow是PIL的一个分支,提供了更多的功能和更好的支持。 二、安装Pillow1pip install Pillow 三、基本操作1. 打开和显示图像123456789101112from PIL import Image# 打开图像img = Image.open('image.jpg')# 显示图像img.show()# 查看图像信息print(f"图像大小:{img.size}")print(f"图像模式:{img.mode}")print(f"图像格式:{img.format}") 2. 保存图像12345678from PIL import Image# 打开图像img = Image.open('im...
Python CSV模块使用指南
一、什么是CSV?CSV(Comma-Separated Values)是一种简单的文件格式,用于存储表格数据,如电子表格或数据库。CSV文件中的每行代表表格中的一行,每行中的值用逗号(或其他分隔符)分隔。 二、Python的CSV模块Python标准库中的csv模块提供了处理CSV文件的功能,它可以帮助你读取和写入CSV文件,处理各种CSV格式的变体。 三、读取CSV文件1. 基本读取123456import csvwith open('data.csv', 'r', encoding='utf-8') as f: reader = csv.reader(f) for row in reader: print(row) 2. 读取为字典123456import csvwith open('data.csv', 'r', encoding='utf-8') as f: reader = csv.DictReader(f) ...
SAX vs. DOM:流式处理与树状模型
一、核心区别:内存快照 vs. 事件流先明确最本质的差异:DOM 解析器会为整个XML文档创建一个内存快照,构建一棵完整的节点树;而 SAX 解析器则像一个事件流处理器,逐行扫描文档并触发事件。这一区别决定了它们在内存占用、处理速度和编程模型上的根本不同,是XML处理技术中“空间换时间”与“时间换空间”的经典对决。 二、分场景深度解析1. DOM:将整个文档“拍”进内存DOM(Document Object Model)的核心思想是一次性加载整个XML文档,在内存中构建一个与文档层级结构完全对应的对象树。这就像给一座建筑拍下一张高清全景照片,所有细节(房间、门窗、楼层关系)都一览无余。 工作原理:解析器从XML文件的根元素开始,递归地读取每个节点,并在内存中创建相应的对象(如 Document, Element, Attr, Text)。这些对象通过父子、兄弟关系相互连接,形成一个完整的对象树。 实现特点: 随机访问:由于整个树都在内存中,你可以随时、随意地访问树中的任何一个节点,向前或向后遍历都极其方便。 易于编程:其API非常直观,符合人们对树形结构的认知,上手简单,代...
func(int) & func(int x)
一、核心区别:参数名的「存在意义」先明确最本质差异:**func(int){}**省略参数名,**func(int x){}**指定参数名x。这一区别在函数「声明」和「定义」场景中影响截然不同,且仅在 C/C++ 等少数语言中合法(Python、Java 等需强制指定参数名)。 二、分场景深度解析1. 函数声明阶段:几乎无差异在头文件或函数原型声明中,两者作用完全一致 ——仅告知编译器「函数接收一个 int 类型参数」,参数名不影响函数签名。 示例: 123// 以下两种声明等效,编译器均识别为「接收int、返回void」的函数void func(int); // 省略参数名(常用)void func(int x); // 带参数名(可选,仅作注释提示) 正如中关村在线问答指出的:声明只需说明参数类型,参数名「没什么用」。编译器处理时,会忽略声明中的参数名,仅记录函数名和参数类型序列。 2. 函数定义阶段:可用性天差地别函数定义(实现)时,参数名的有无直接决定「能否在函数体内使用该参数」: func(int x){}:可正常操作参数 x是参数的...
拒绝死记硬背!用 C++ 的底层逻辑,彻底搞懂 Python 的“魔术方法”
一、引言:打破“魔法”的迷信初学者看到 __init__、__str__ 这种双下划线方法就头大,只能死记硬背。但对于C++程序员来说,这些其实就是编译器在特定时刻自动调用的“钩子函数”。 二、核心类比 Python 的 obj + obj 对应 C++ 的 operator+ 重载 Python 的 str(obj) 对应 C++ 的 operator std::string() 或 toString() 虚函数 Python 的 cls 对应 C++ 的 static 类作用域 三、变身术:类型转换协议 (str vs int)1. __str__ (人类视图) C++ 类比:相当于 C++ 中重载 std::ostream& operator<<(std::ostream&, const T&) 触发时机:当你执行 print(obj) 或 str(obj) 时 用途:返回一个人类可读的字符串 2. __repr__ (机器视图) C++ 类比:相当于调试器中显示对象的逻辑 触发时机:当你在交互式终端中直接输入对象名并回车时 用途:返...
Python装饰器本质深度解析
一、装饰器的本质装饰器本质上就是高阶函数加语法糖。你想啊,装饰器做的事情就是:接收一个函数,包一层,返回一个新的函数。这不就是典型的高阶函数吗? @decorator 等价于 func = decorator(func),就是把原函数传给装饰器,装饰器决定什么时候调用它、传什么参数进去,然后再返回一个升级后的函数。 二、装饰器的基本结构让我们来看一个最简单的装饰器: 1234567891011121314def simple_decorator(func): def wrapper(*args, **kwargs): print("Before function call") result = func(*args, **kwargs) print("After function call") return result return wrapper@simple_decoratordef say_hello(name): print(f"Hello, ...
Python正则表达式re模块核心功能详解
在Python中,处理正则表达式的标准库是re。你可以把它想象成一把文本处理的“瑞士军刀”,专门用来在海量文本中查找、提取、替换或验证特定格式的字符串。 一、核心工具箱:5个最常用的方法在使用前,记得先导入模块:import re 方法 作用 形象比喻 返回值 re.match() 从开头匹配 “必须从门口进入” 匹配成功返回对象,失败返回None re.search() 扫描全文找第一个 “在屋里找一遍,找到就停” 匹配成功返回对象,失败返回None re.findall() 找到所有匹配项 “把所有符合条件的都抓出来” 列表 ['a', 'b', ...] re.sub() 替换文本 “把这里的A换成B” 替换后的新字符串 re.split() 按规则分割 “按这个符号切开” 分割后的列表 二、代码实战:一看就懂1. 查找与提取(search vs findall)如果你想提取文本中的手机号或数字: 123456789101112import retext = "我的手机号是 13800138000,备...
Python正则表达式re.IGNORECASE使用指南
一、什么是re.IGNORECASE?re.IGNORECASE是Python re模块中的一个标志(Flag),用于在执行正则表达式匹配时忽略字母的大小写。它的简写形式是re.I。 二、为什么使用它?默认情况下,正则表达式是区分大小写的。例如,模式python只能匹配小写的"python",无法匹配"Python"或"PYTHON"。使用re.IGNORECASE可以解决这个问题,让匹配过程对大小写不敏感,这在处理用户输入、日志分析或关键词搜索时非常实用。 三、如何使用?1. 在函数中直接使用123456789101112import retext = "The quick Brown fox jumps over the lazy dog."pattern = "brown"# 不加re.IGNORECASE,匹配失败result1 = re.search(pattern, text)print(result1) # 输出: None# 加上re.IGNORECASE,成功匹...
函数对象
一、函数对象的本质函数对象(也称为仿函数,Functor)是*重载了函数调用运算符***operator()**的类或结构体的实例。这种特殊的设计使它能够像普通函数一样被调用,同时又具备对象的所有特性。 12345678910111213141516// 一个简单的函数对象类struct Add { // 重载函数调用运算符 int operator()(int a, int b) const { return a + b; }};// 使用方式int main() { Add add; int result = add(3, 5); // 像函数一样调用对象 // 也可以直接使用临时对象 int result2 = Add()(10, 20); return 0;} 从本质上讲,函数对象是一个带行为的对象,而普通函数是一段可执行代码。这种本质差异决定了它们在功能和适用场景上的不同。 二、函数对象与普通函数的核心区别2.1 状态管理能力这是两者最根本的区别...
Python模块与包深度解析
一、什么是模块?在Python中,模块是一个包含Python定义和语句的文件。文件名就是模块名加上.py后缀。例如,一个名为my_module.py的文件就是一个名为my_module的模块。 二、导入模块1. 基本导入1234import my_module# 使用模块中的函数my_module.say_hello() 2. 导入特定函数1234from my_module import say_hello# 直接使用函数say_hello() 3. 导入所有函数1234from my_module import *# 直接使用模块中的所有函数say_hello() 4. 导入并别名12345678910import my_module as mm# 使用别名访问模块mm.say_hello()# 或者from my_module import say_hello as sh# 使用别名访问函数sh() 三、模块的搜索路径当你导入一个模块时,Python会按照以下顺序搜索模块: 当前目录 PYTHONPATH环境变量中指定的目录 标准库目录 任何.pth文件中指定的目...
C++ Lambda 表达式
导言在现代 C++ 开发中,lambda 表达式(匿名函数)已经成为编写简洁高效代码的重要工具。尤其在配合 STL 算法(如for_each)时,lambda 表达式能够消除编写命名函数或函数对象的额外开销,使代码更加紧凑直观。 一、Lambda 表达式的基本语法lambda 表达式的完整语法结构如下: 123[capture](parameters) mutable noexcept -> return_type { // 函数体} 各组成部分的含义: [capture]:捕获列表,定义 lambda 表达式可以访问的外部变量 (parameters):参数列表,与普通函数的参数列表类似 mutable:可选修饰符,允许修改按值捕获的变量 noexcept:可选修饰符,指定函数不会抛出异常 -> return_type:返回类型,当函数体只有 return 语句时可省略 {}:函数体,包含具体的执行逻辑 1.1 最简单的 Lambda 表达式最简化的 lambda 表达式可以省略参数列表、返回类型和修饰符,仅保留捕...
模板实现堆排序算法
导言堆排序是一种基于二叉堆数据结构的高效排序算法,具有 O (n log n) 的时间复杂度和原地排序的特性。使用模板实现堆排序可以使其灵活适用于各种数据类型,并支持自定义比较规则。 一、堆排序算法原理堆排序主要分为两个阶段: 建堆阶段:将无序数组构建成一个二叉堆(最大堆或最小堆) 排序阶段:反复提取堆顶元素(最大值或最小值),并调整剩余元素维持堆特性 二叉堆是一种完全二叉树,对于最大堆,每个父节点的值大于或等于其子节点的值;对于最小堆,每个父节点的值小于或等于其子节点的值。 二、模板类实现下面是完整的HeapSort模板类实现,基于提供的框架结构: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788#include <vector>#include <functional>...
Python文件操作深度解析
一、文件操作的基本概念在Python中,文件操作是一个非常基础但重要的功能。Python提供了多种方式来处理文件,包括打开、读取、写入、关闭等操作。 二、文件的打开与关闭1. 基本打开方式12345# 打开文件f = open('file.txt', 'r')# 关闭文件f.close() 2. 使用with语句为了避免忘记关闭文件,我们可以使用with语句,它会自动处理文件的关闭: 1234with open('file.txt', 'r') as f: # 处理文件 pass# 文件会自动关闭 三、文件的读取1. 读取整个文件123with open('file.txt', 'r') as f: content = f.read() print(content) 2. 逐行读取123with open('file.txt', 'r') as f: for line in f: ...
C++ 模板实现快速排序算法
导言快速排序是一种高效的分治排序算法,平均时间复杂度为 O (n log n)。使用 C++ 模板实现快速排序可以使其适用于各种数据类型,配合比较器还能灵活调整排序规则。 一、快速排序算法原理快速排序的核心思想是: 选择一个元素作为 "基准"(pivot) 将数组分区,所有比基准值小的元素移到基准前面,比基准值大的元素移到基准后面 递归地对前后两个子数组进行排序 这种分治策略使快速排序成为实际应用中最快的排序算法之一。 二、模板类实现下面是完整的MyQsort模板类实现,支持任意可比较的数据类型和自定义比较规则: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687#include <vector>#include <functional>#include &...
unordered_map存放自定义类具体实现
一、引言上一篇文章介绍了unordered_map存放自定义类型的六种方法的理论框架,本文将通过完整可运行的代码示例,详细展示每种方法的具体实现细节。这六种方法是通过 2 种哈希实现方式与 3 种相等性比较方式组合而成,每种组合都有其独特的实现要点。 二、基础准备首先定义基础的Point类和测试函数,作为六种方法的共同基础: 12345678910111213141516171819202122232425262728293031323334353637383940#include <iostream>#include <unordered_map>#include <string>#include <functional>// 自定义点类型class Point {private: int x; int y;public: Point(int x_ = 0, int y_ = 0) : x(x_), y(y_) {} int getX() const { re...
Python海象运算符深度解析
一、什么是海象运算符?海象运算符(Walrus Operator)是Python 3.8引入的新特性,它的语法是:=,读作“赋值表达式”。这个运算符的名字来源于它的外观,:= 看起来像一只眼睛和两颗长牙的海象。 二、与C++=运算符的区别与C++中=运算符不同,Python中的:=运算符在赋值后返回结果,而不是赋值前返回结果: C++:=运算符在赋值前返回结果,而不是赋值后返回结果 Python::=运算符在赋值后返回结果,而不是赋值前返回结果 三、海象运算符的使用场景1. 在if语句中12345678# 传统写法user_input = input("请输入:")if user_input: print(f"你输入了:{user_input}")# 使用海象运算符if (user_input := input("请输入:")): print(f"你输入了:{user_input}") 2. 在while循环中123456789# 传...
unordered_map 存放自定义类型的六种方法
引言std::unordered_map是 C++ 标准库中提供的无序关联容器,与std::map不同,它通过哈希表实现,因此需要两个关键组件:哈希函数(用于计算键的哈希值)和相等性比较函数(用于判断两个键是否相等)。当使用自定义类型作为unordered_map的键时,我们需要显式提供这两种组件。 一、核心概念std::unordered_map的模板定义如下: 1234567template< class Key, class T, class Hash = std::hash<Key>, // 哈希函数类型 class KeyEqual = std::equal_to<Key>, // 相等性比较类型 class Allocator = std::allocator<std::pair<const Key, T>>> class unordered_map; Hash类型必须满足Hash概念:Hash对象的operator()接受const Key&参数,返回s...

