学习笔记: 从C语言基础到Python基础的过渡
1.前言
本文章的旨在整理C语言与Python在基础入门知识方面的差距,从而辅助各位开发者完成从C语言基础到Python基础的过渡。
本文期望的主要面向群体是初学者以及相关专业大学生,需要对C语言有大学通识课级别的掌握能力,以及独立思考的能力。
同时这也是我的学习笔记。必须强调的是,虽然我在中学阶段略微接触过一些Python,但真正的系统性学习其实发生在近期。因此,本文仅体现个人的、入门级别的思考和理解,是为了写而写,写出来用来巩固自己的知识体系。
当然,我会尽量保证文中的所有知识是正确且完备的。
如果存在明显的事实性错误,请立刻联系我,保证错误被及时更正。
关于Python的进阶知识与特性,我没有能力也没有资格去进行讲述,希望各位能够在本文的辅助下打好基础,而后自主地进一步学习Python,并真正地掌握这门语言。
斜体部分为基础知识补充,并不要求掌握。
2.编程环境
C语言
我们先试着复习学习? 下基于C语言的开发流程是如何运作的。其主要涉及三个方面:
-
文本编辑器(Text Editor):开发者通过C语言撰写
.c
和.h
文件,是开发者的主要工作环节。 -
编译器(Compiler):编译器将.c与.h文件翻译成机器可以执行的目标文件(
.obj
/.o
)或可执行文件(.exe
/ 无扩展名)。同时编译器还负责静态检查,包括语法检查和明显的逻辑漏洞,以及编译过程中的优化行为。 -
链接器与运行环境(Linker & Runtime):编译完成后,程序的各个部分通过链接器合并成一个完整的可执行文件。而执行完成的文件依赖操作系统提供的运行时支持(Runtime)。
在现在的开发环境中,大多数情况下,我们已经不再关心这个流程,而是使用IDE(Integrated Development Environment,集成开发环境) 来简化整个流程。但为了方便讲解,我们仍然在这里将其一一指出。
总结: C语言的环境需要“编写 + 编译 + 链接 + 运行”四步。
Python
Python是一门解释型语言(在靠后的章节会重点讲述这一点),因此它并不需要经过“编译”这一过程。这使得Python 的开发环境比 C 更轻量、更灵活。
同时,这也就引入了新的概念,Python 解释器(Interpreter)。
最常见的解释器是CPython,这也是官方提供的解释器。我们在电脑中安装的Python 3.8,Python 3.13,其实指的就是Python 解释器本身的版本号。
顾名思义,CPython就是用C开发的Python解释器,除此之外还有在交互式方面增强的IPython,为Java平台开发的Jython,以及速度快的PyPy等解释器,在生产中应当根据需要进行挑选。
这里给出CPython 3.13.8(Windows 64位)的下载链接
解释器在整个开发流程中扮演的角色,有点类似于 C 语言的“编译器 + 链接器”,但工作方式完全不同:C 语言在运行前就会生成可执行文件;而 Python 的解释器则是在程序运行时逐行读取、翻译并执行代码。
换句话说,Python 并不是“先编译再运行”,而是“边运行边解释”。
而开发者的主要工作仍然集中在文本编辑器这一环节,即用 Python 语法编写脚本文件(.py
),再由解释器直接运行。
总结: Python的环境需要“编写 + 边解释边运行”两步。
环境变量配置
程序和可执行文件可以在许多目录,而这些路径很可能不在操作系统提供可执行文件的搜索路径中。
有时候Python的安装是不会自动配置环境变量的。这可能会导致一些问题,比如下文的命令行没有办法识别到Python。
如果出现了这些情况,我会建议你访问这个教程的环境变量配置章节。照着教程改就完事了,没有什么讲的必要。
Python的运行
在初学者阶段,Python的运行主要是通过Python控制台(Python Console)来实现的。
现在介绍两种启动控制台的形式。
1.命令行
Windows平台下通过cmd或PowerShell,而macOS / Linux通过Terminal。唤出操作系统的命令行控制台后,输入命令
python
或指定版本
python3
以上两种命令可以进入Python的交互式模式(REPL)。此时你可以输入任意一行代码,敲下回车,这行代码就会被立刻解释和运行。这十分适合小体量下的Python使用,比如为了调试或者学习语法。
当然,命令行也可以用来直接运行脚本:
python your_file.py
2. IDE
常见的Python IDE内置Python解释器和Python控制台。当然启动控制台的方式会有所区别。对初学者来说,IDE内置的控制台相比于操作系统的命令行要更加利于使用,在结合脚本运行方面也更加便捷。
除了控制台以外,生产环境中更常见的方式,是通过其他应用程序调用 Python 脚本来执行任务。例如,在 GitHub Actions 的 workflow 中,我们常用 Python 脚本自动化一些维护工作。另外,在类 Unix 系统上执行脚本时,应当确认脚本具有可执行权限。
IDE推荐
Visual Studio Code
简称VSCode,一款由微软开发且跨平台的免费源代码编辑器。下载链接放这。
VS Code 本身并不自带任何编译器或解释器,它只是一个轻量级的文本编辑器。
为了适应 Python 开发,我们需要安装相应的扩展。最基本的是 Python 扩展,后续还可以根据自己需求加装Lint 工具、调试器、AI助手等。
实际上,正是通过这些扩展,VS Code 才能具备 IDE 的功能,成为一个完整的开发环境。
具体的安装教程请参照菜鸟教程。人家讲的比我详细的多,我不再赘述。
PyCharm
由 JetBrains 公司提供的 永久免费 Python IDE。相比于 VS Code 依赖大量扩展,PyCharm 本身集成了丰富的工具,是更为专业的 Python 开发环境。
对初学者来说,PyCharm 可以省略安装 Python 解释器和配置环境变量的步骤,同时提供成熟的文本格式化、代码重构等功能,降低入门门槛。
3.基本语法
这是本篇文章最重要的部分了,让我们开始吧。
我通过对比同一个需求在不同语言下的实现方式,来讲述这两种语言的相同点与不同点
需求:在某条件下,声明若干个变量
if(value == 1){int count = 1;double score = 2.0;if(high){float height = 1.74f;float mess = 50;}
}
if value == 1:count = 1score = 2.0if high :height = 1.74mess = 50
语句区分
C语言通过分号;
来区分语句。每一个语句以分号结尾。多个语句可以写在同一行。虽然你没有任何理由这么做。
Python通过换行来区分语句。每一行就是一个语句。在需要的情况下,可以在同一行中使用多条语句,语句之间使用分号;
分割。
代码组(代码块)
C语言的代码块通过花括号{}
来将若干个语句构成代码块
-
比如上文的line2~6被花括号合并成了一个代码块,从而使得这些语句都受
if
的控制。而line5~6又被内层花括号括上,形成了代码块的嵌套 -
一般来说,一层代码块内部会增加一层缩进,但这层缩进不是C语言的一部分,只是为了更好的可读性,辅助开发者识别这些组合、嵌套关系。
Python将缩进相同或更深的一组相邻语句构成一个代码块,我们称之代码组。
-
如图中所示,line2~6是≥1次缩进,且中间没有被更浅层的缩进的语句打断,所以他们组成了一个代码块。同时line5~6是2次缩进,所以他们组成了代码块里的代码块,参考C语言那部分的嵌套关系。
-
注意空行是不会影响代码块的。即使两行相同缩进的代码之间隔一百个空行,它们也仍然在同一个代码块里。
-
区别就在这里了,Python完全依赖缩进来区分代码块。缩进就是代码的一部分。
-
像
if
、while
、def
和class
这样的复合语句,首行以关键字开始,以冒号( : )结束,该行之后的一行或多行代码具备相同或更深的缩进,从而构成代码组。 -
我们将首行及后面的代码组称为一个子句(clause)。
总的来说,我们不妨这么去过渡:
把Python里面的所有语句除去空语句之后,把相邻语句里,
比上一句多了一层缩进的,当做其前方有一个C语言的{
比下一句多了一层缩进的,当做其后方有一个C语言的}
变量的声明与赋值
在编程中,变量(Variable)是用来存储数据的容器。不同语言对变量的声明和赋值方式有所不同
在 C 语言中,变量必须先声明类型,然后才能使用:
int count = 10; // 声明一个整型变量 count,并赋初值 10
double score = 95.5; // 声明一个双精度浮点数 score
char grade = 'A'; // 声明一个字符变量 grade
-
声明:告诉编译器变量的类型和名字。
-
赋值:给变量一个初始值。
-
在 C 中,如果只声明不赋值,变量会包含随机的内存值:
int temp; // 未赋值,内容未知
Python 是 动态类型语言,不需要显式声明变量类型,解释器会根据赋值内容自动推断类型:
count = 10 # 整型
score = 95.5 # 浮点型
grade = 'A' # 字符串
-
Python 中赋值时,变量名就是创建变量的时刻。
-
同一个变量可以被重新赋值为不同类型的值:
count = 10 # 整型
count = 10.5 # 现在变成浮点型
总结:
特性 | C 语言 | Python |
---|---|---|
类型声明 | 必须显式声明 | 自动推断 |
动态类型 | 否 | 是 |
可变类型 | 固定 | 可变,可重新赋值为不同类型 |
未初始化使用 | 会出现随机值 | 直接赋值时才创建变量 |
注意:Python 并不是“没有类型”。
每个变量在 Python 中都有类型(int、float、str 等),只是类型由解释器在运行时动态推断,而不是由程序员在编写时显式声明。
这样的特性对有些人来说是十分方便的,但至少就我身边的开发者来说,我们普遍认为这样的设计为开发时的静态分析(Static Analysis)带来了不少困难。
常用数据类型
1. 整数
-
C:
int
,long
,short
-
固定大小(32位、64位视平台而定)
-
支持有符号和无符号
-
-
Python:
int
-
整数大小没有限制(任意精度)
-
自动管理内存
-
2. 浮点数
-
C:
float
,double
,long double
-
精度固定,受平台限制
-
需要注意浮点数精度误差
-
-
Python:
float
-
通常对应 C 的
double
-
精度比 C float 高
-
还可以用
decimal.Decimal
做高精度计算
-
3. 布尔值
-
C:没有原生
bool
(C99 之后有_Bool
或stdbool.h
)- 通常用
0
表示 False,非 0 表示 True
- 通常用
-
Python:
bool
-
True
/False
-
与整数可以互转:
int(True)=1
,int(False)=0
-
4. 字符/字符串
-
C:
-
字符:
char
-
字符串:字符数组
char str[10]
+\0
结束 -
操作复杂,需要使用库函数(
strlen
,strcpy
等)
-
-
Python:
-
字符串:
str
-
可以直接用引号定义:
'a'
或"hello"
-
支持索引、切片、拼接、长度查询等
-
5. 指针问题
我们在C语言中学习了令许多初学者头昏脑涨的指针。它指向一块内存空间,并涉及取地址、解引用、偏移等概念。
幸运的是,Python抛弃了指针,这是Python 设计的高层抽象之一。
在 Python 中,变量名本质上是指向对象的引用。
然而,引用(reference)这个概念,在C语言中尚未涉及,我只能尝试进行解释:
引用(reference):
-
描述变量和内存中实际对象之间的关系。
-
可以理解为“变量名指向对象”,类似 C 语言的指针,但更安全。
-
在 Python 中,所有变量都是引用,无论对象是否属于类。
6. 容器
容器是一种用于存放多个数据的对象。
在C里面,与之最接近的概念是数组。我们都学过,数组有固定的长度,占用固定的内存。对于数组内元素的修改方式是直接编辑,读取方式是通过索引或者指针。
而在高级语言(C++、Python、Java、C#)里,容器是一个十分常见的概念。它通常要提供以下功能:
-
存放数据的能力
-
访问和修改数据的方法
-
数据组织结构(顺序、映射、集合等)
这是比较抽象的概念,用我的话来说,一个容器至少要能够实现:
-
对于容器,能够往里面加东西,也能把东西从里面删掉。
-
给定一个容器,能知道它里面有什么东西。
-
给定一个东西和一个容器,能够知道这个东西是否在容器里。
- 列表(list)
-
可以存放不同类型的元素。
-
元素可以被增加或减少。
-
有序,可以通过索引来获取。
-
当往中间位置插入新元素时,这个位置之后的所有元素自动后移
-
当往中间位置删除元素时,这个位置之后的所有元素自动前移
- 集合(set)
-
可以存放不同类型的元素,但类型必须能够给出哈希值。
-
元素可以被增加或减少。
-
无序。
-
不可重复。添加相同哈希值的元素将不会有任何作用。
- 元组(tuple)
-
可以存放不同类型的元素。
-
元素是不可变的。不能增加也不能减少。
-
有序,可以通过索引来获取。
- 字典(dict)
-
可以存放不同类型的键值对(Key-value pair)。即每一个元素由一个键和一个值组成。
-
键必须是不可变类型(int, str, tuple 等),值可以是任意对象。
-
元素可以被增加或减少。
-
一般以无序处理,但在Python 3.7+ 遍历顺序保持插入顺序。
-
可以通过键来访问对应的值。
-
以键值对的形式新增元素。
-
可以通过键来移除一整个键值对。
-
键是唯一的,但不同键之间的值可以重复。
最后用一张表格来概括。
容器/类型 | 可变性 | 有序 | 允许重复 | 元素类型限制 | 用途/特点 |
---|---|---|---|---|---|
C 语言数组Array | 固定长度 | 是 | 是 | 同类型(同类型的连续内存) | 静态序列,需要指定长度,效率高 |
列表list | 可变 | 是 | 是 | 任意类型 | 动态序列,可增删改,灵活 |
集合set | 可变 | 否 | 否 | 任意可哈希类型 | 集合运算、去重 |
元组tuple | 不可变 | 是 | 是 | 任意类型 | 不可变序列,可作为字典键或固定数据 |
字典dict | 可变 | 有序(3.7+) | 键唯一 | 键不可变,值任意 | 键值映射,快速查找 |
7. 内存管理问题
这一部分是底层,不要求掌握。
在C语言中,内存区分堆和栈。
栈(stack)
-
栈用于存储局部变量、函数参数和返回地址。
-
生命周期短:随函数调用入栈,函数返回出栈。
-
栈上的变量 自动分配和释放,不需要程序员手动管理。
- 堆(heap)
-
堆用于存储 动态分配的对象,大小可变且生命周期不受函数调用限制。
-
需要程序员手动管理内存(
malloc/free
或new/delete
)。
在 Python 里,栈和堆的概念不像 C 那样直观,因为 Python 使用了自动内存管理和对象模型。
栈主要保存变量名(名称/引用),即“指向对象的指针”。
堆保存 对象本身,比如整数对象 5 和 6,列表对象 [1,2,3]
等。
Python 的对象都是在堆上分配的,堆上的对象由解释器管理,自动垃圾回收。
这还涉及到另一个概念:可变对象与不可变对象
-
不可变对象(int、float、str、tuple)
-
对象在堆上创建
-
栈上的变量引用它
-
改变引用 → 创建新的对象 → 栈上的引用改变,堆上的原对象不变
-
-
可变对象(list、dict、set)
-
对象在堆上创建
-
栈上的多个变量可以引用同一个对象
-
修改对象 → 堆上的内容改变,所有引用可见
-