这几年人工智慧这个概念还是蛮火的,自从 OpenAI 端出了他们的看家神器 GPT 模型,人类仿佛一夜之间进入了第四次科技革命。随着人工智慧领域的蓬勃发展,其底座 Python 语言也逐渐成为了程序员们的宠儿。Python 语言的简洁、优雅、易读易写,以及强大的生态系统,使得它成为了人工智慧领域的首选语言。近些年更是迅速发展,一举成为 C 语言之外的另外一门编程入门级语言。
作为一个从 C 语言时代一路走来的老头,以及一个 C Family Fans,我在相当长的时间里都对 Python 保持着一种“不屑一顾”的态度。尽管到现在慢慢接受了,却也仍然用的比较少。但我认为,随着我在我个人的医学科研领域的精进,会越来越多地用到 Python 这门语言,而平时随手写一个 Python 脚本帮我处理一些事情,似乎也越发跟手。
因此,我还是决定写下这篇文章,作为一个 Python 的入门教程,供大家参考。这篇文章的目标读者是那些对编程一无所知的新手,或者是对 Python 语言感兴趣的人。我会尽量用最简单的语言,最直观的例子,来让大家了解 Python 这门语言的基本语法和特性。So, let’s get started!
Python 是一门解释型语言
关于编译与解释的概念,我在其他的影片中有提到过,但是为了这篇文章的完整性,我还是要再次提一下。
程序员给计算机下达的指令称为“代码”,代码是用编程语言写成的,比如我们常说的 C 语言、C++、Java、Python 等,都属于编程语言。编程语言是一种人类经过训练可以书写并理解的语言。然而,计算机并不懂人类的语言,它只懂机器语言,也就是二进制代码。如果你了解过二进制,或者之前有了解过相关的科普,你就会知道,二进制代码是由 0 和 1 组成的,其中 0 代表 CPU 的电平低电压,1 代表 CPU 的电平高电压。换句话说,计算机的 CPU 只能理解 0 和 1 的超长组合,而不理解代码中的字母、数字和符号。
这时候,我们就需要一个翻译官,来将我们写的代码翻译成计算机能够理解的机器语言。翻译官有两种翻译方式,一种是把你写好的代码文件预先翻译成一份机器语言文件,当计算机每一次要执行的时候,直接读取这份机器语言文件,这种翻译方式就是编译;另一种则不预先翻译,而是在计算机执行的时候,边读取代码文件边翻译,这种翻译方式就是解释。
以下两张图片显示了编译和解释的路径:
- 编译:
- 解释:
乍一看,似乎解释比编译要少走一步,似乎更优。但实际上,两者各有千秋。
很容易理解,编译的优点是执行效率高,执行速度快。因为机器直接阅读翻译好的机器码文件,速度要远远高于解释。这就像是美国大使直接阅读一份英文的文件,总是要比一个口译员现场翻译要快。缺点也很明显,一旦代码有所改动,就需要重新编译,生成一份新的机器码文件。这就像是那份中文文件有所改动,翻译官就需要重新校对全文,重新翻译一样,非常麻烦。
而解释则避免了这一点,代码改动后,无需重新翻译出一份机器码。就像是口译员现场翻译,只要口译员能够理解中文,就能够实时翻译成英文。但缺点也很明显,执行效率低,因为计算机每次执行都需要现场翻译,速度远远低于编译。
一门编程语言是以编译还是解释的方式执行,事实上是由其最流行的执行方式决定的。比如,C 语言最流行的是其编译器,因此 C 语言更多被作为一门编译型语言;而 Python 最流行的是其解释器,因此 Python 更多被作为一门解释型语言。但是,如果有人就是想给 Python 写一个编译器,那么 Python 也可以成为一门编译型语言。映射进现实,反正那份中文文件就在那里,你是想现场口译还是预先翻译,全看翻译员个人喜好。
Python 是一门解释型语言,这意味着你写好的 Python 代码文件,是由 Python 解释器在计算机上实时翻译成机器码执行的。这也意味着,你可以在计算机上安装 Python 解释器,然后直接运行你写好的 Python 代码文件,而不需要额外的编译步骤。
你的第一个 Python 程序
在我们圈内,有个不成文的规定,或者说是习俗,那就是开始学习一门新的语言的时候,用该语言第一个写出的程序应该是在控制台打印出一句“Hello, world.”我们也不例外。
打开你的 WebStorm,新建一个 Pure Python 工程,取名叫 learn-python,venv 则根据个人喜好,如果喜欢用 conda,则切换到 base conda 的选项,否则使用第一个即可。
而后我们在工程根目录下创建一个main.py
文件,在其中输入这样一句话:
1 | print('Hello, world.') |
然后点击运行按钮,你就会在控制台中看到输出结果。
Congratulations! 你成功开发了你的第一个 Python 程序。print()
用于向控制台打印一句话。
变量
变量的概念在绝大多数编程语言中都会有。然而许多程序员终其生涯都未能理解变量到底是什么。我们先来看 Python 中一个变量是如何定义:
1 | variable = 1 |
这句话是什么意思呢?如果用从未接触过编程的新手的语言来讲,就是我在内存中开辟了一块内存空间,把这块内存空间命名为 variable,并把一个数字 1 塞入这块内存空间。
所以明了了,变量就是一块内存空间。至于内存的概念,我之前也有为大家扫过盲,高速存储、断电丢失的那个东西就是内存,台湾的话叫“記憶體”。
变量变量,当然是可变的量才叫变量。也就是说,这块内存空间里的东西是可以被后塞入的东西改变的。比如:
1 | variable = 1 |
一句题外话,上面的代码中,#
是注释符号。什么是注释?注释是为了方便程序员看懂代码而写的一些文字,解释器在解释代码的时候会忽略掉注释。因此你可以在注释里写任何你想写的东西,解释器都不会管。比如:1
variable = 1 # 老板让加班,我不干,他要是敢说我,我就把这个变量改成 0,我保证让他吃不了兜着走。
在 Python 中,注释有两种写法,单行注释和多行注释。单行注释就是在一行代码后面加一个#
,多行注释则是用三个单引号'''
或者三个双引号"""
包裹起来。比如:
1 | # 这是单行注释 |
回到正题上来,上面的代码执行结果是,两个print()
函数分别输出 1 和 2。这是因为,第一次输出,variable
这块内存空间中的内容是 1,所以输出 1;然后第二次,variable
这块内存空间中的内容被改成了 2,所以输出 2。
向变量中塞入东西的过程,叫做赋值。赋值的符号是=
。在 Python 中,赋值是从右往左的,也就是说,等号右边的东西被塞入等号左边的变量中。
所以这就和我们所学的数学中的等号不一样了。在数学中,等号是左右两边的东西相等,是一个判断的过程。而在 Python 中,等号是赋值的过程,是一个操作的过程。换句话说,在 Python 中,variable = 1
和1 = variable
是不一样的,前者是把 1 塞入 variable 中,后者是把 variable 塞入 1 中(这显然是不可能的)。
再来,变量的名字是有规定的。变量的名字必顫是字母、数字、下划线的组合,且不能以数字开头。比如,variable
、variable1
、variable_1
都是合法的变量名,而1variable
、variable-1
、variable 1
则都是不合法的变量名。此外,Python 是大小写敏感的。也就是说,variable
和Variable
是两个不同的变量名。
Python 中的变量名也不可以是 Python 的关键字。关键字是 Python 语言中已经被定义好的,有特殊含义的单词。比如,print
、if
、else
、for
等等,都是 Python 的关键字,不能用作变量名。关键字表可以在这里查看:Python Keywords。
数据类型
数字
数字是最好理解的,比如 1 + 1 = 2
中的 1 和 2,都属于数字类型。在 Python 中,数字类型被定义为“可以进行数学运算的数字类型”。如果细分,又可以分为四类:
- 整型,即整数,0,1,2……等。
- 浮点型,即小数,3.1415926,1.5,1.6……等。
- 长整型,即取值范围比较长的整数,也可以表示 8 进位和 16 进位的数字。
- 复数型,表示复数。
字符串
接下来就是对新手的经典难题,123
和 "123"
有没有区别?你看我都这么问了,那肯定是有区别的对吧?看形式也能看出来,一个没有引号,另一个则是由引号包裹。
我们把任何有单引号或双引号包裹的内容连同包裹的引号,叫做字符串。比如"123"
、'abc'
、"abc123"
、'a1b2c3'
都是字符串。
我们来做一个加法,就知道其区别了:
1 | print(123 + 123) # 输出 246 |
字符串之间用+
的操作叫做“字符串拼接”。而最后的结果123123
仍是一个字符串。
列表
列表是 Python 中使用最频繁的数据类型之一。列表类型,是多个变量的集合类型。
1 | list = [1, "Hello, world", 1.5] |
列表类型用[]
包裹。列表中的值以下标取出。比如:
1 | list = [1, "Hello, world", 1.5] |
注意,列表的下标以0
开始,而不是常见的1
开始。上面的例子list[0]
为1
,list[1]
为"Hello, world"
,list[2]
为1.5
。如果想取列表中的连续值,可以使用区间下标,就像list[0:1]
那样,取出的仍然是一个列表。区间下标是前闭后开区间。
列表可嵌套。比如:
1 | nested_list = [[1, 2, 3], ["Hello", "world"]] |
取值的时候则是安排连续下标:
1 | nested_list[0][1] # 输出 2 |
上面的取值过程,[0]
取出的是[1, 2, 3]
,[1]
则是从取出的[1, 2, 3]
中取出2
。
元组
元组用()
包裹,与列表相似,但不能修改其中的内容,是只读列表。
1 | tuple = (1, "Hello, world", 3.1415926) |
字典
我们刚刚说的列表和元组,有最大的问题,就是其中的每一个值都没有单独的名字,只能通过整个列表或元组的名字,用下标来取值。字典用{}
包裹。
而字典则解决了此问题。字典可以将集合中每一个元素都取一个名字,之后取值、改值都可以使用名字来做。
1 | dict = { "str": "Hello, world.", "num_1": 1, "num_2": 3.1415926 } |
Python 是一门动态类型语言
之前讲变量的时候,我们有过如此的一段变量:
1 | variable = 1 |
那么,如果我想要把variable
的值从1
改到"Hello, world."
,可以做到吗?答案是可以。这种跨类型的改值之所以能够实现,皆是因为 Python 灵活的动态数据类型。
1 | variable = 1 |
运算符
算术运算符
运算符 | 描述 | 实例 |
---|---|---|
+ | 加 | 1 + 1 = 2 |
- | 减 | 2 - 1 = 1 |
* | 乘 | 2 * 2 = 4 |
/ | 除 | 1 / 2 = 0.5 |
% | 余 | 3 % 2 = 1 |
** | 幂 | 2**4 = |
// | 向下取整 | 9 // 2 = 4 |
比较运算符
运算符 | 描述 | 实例 |
---|---|---|
== | 等于 | 1 == 1,结果为 True |
!= | 不等于 | 1 != 1,结果为 False |
> | 大于 | 2 > 1,结果为 True |
< | 小于 | 2 < 1,结果为 False |
>= | 大于或等于 | 2 >= 1,结果为 True |
<= | 小于或等于 | 2 <= 1,结果为 False |
赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
= | 赋值运算 | c = a + b,将 a + b 的运算结果赋值给 c |
+= | 加法赋值运算 | c += a,相当于 c = c + a |
-= | 减法赋值运算 | c -= a,相当于 c = c - a |
*= | 乘法赋值运算 | c = a,相当于 c = c a |
/= | 除法赋值运算 | c /= a,相当于 c = c / a |
%= | 取余赋值运算 | c %= a,相当于 c = c % a |
**= | 取幂赋值运算 | c = a,相当于 c = c a |
//= | 整除赋值运算 | c //= a,相当于 c = c // a |
逻辑运算符
运算符 | 描述 | 实例 |
---|---|---|
and | 与运算,只有当两边值均为真,结果才为真 | True and True,结果为 True; True and False,结果为 False; False and False,结果为 False |
or | 或运算,两边值有一个为真,结果就为真 | True or True,结果为 True; True or False,结果为True; False or False,结果为 False |
not | 非运算,把 True 变为 False,把 False 变为 True | not True,结果为 False; not False,结果为 True |
成员运算符
运算符 | 描述 | 实例 |
---|---|---|
in | 元素在序列中 | 1 in [1, 2, 3],结果为 True |
not in | 元素不在序列中 | 2 not in [1, 3, 4],结果为 True |
身份运算符
运算符 | 描述 | 实例 |
---|---|---|
is | 两个变量是同一块内存空间 | a is b |
is not | 两个变量不是同一块内存空间 | a is not b |
基本数据类型的操作
数字
数字类型的操作多以数学计算为主。简单的加减乘除余用运算符即可完成。复杂的数学计算则需要特定的函数来完成。
Python 中有两个模组负责处理数学运算,分别是math
和cmath
。限于篇幅,此处不展开,可于Python Math和Python Cmath查看。
字符串
截取子串:1
2
3
4str = "Hello, world."
print(str[1]) # 输出 e
print(str[1:4]) # 输出 ell
print(str[:4]) # 输出 Hell
字符串拼接:1
2
3
4str_1 = "Hello, "
str_2 = "world."
number = 2333
print(str_1 + str_2 + number) # 输出 Hello, world.2333
字符串格式化:字符串格式化可在字符串中插入变量值。
1 | # 格式化字符串取值须以f""包裹 |
转义字符:有一些特殊的字符,比如换行、回车等,需要通过转义字符来实现。比如\n
表示换行,\t
表示一个横向制表位,\r
表示一个回车。你可以在W3C School Python Escape Characters找到关于转义字符的信息。
高级操作:对于字符串的高级操作,比如大小写转换等,可以使用 Python 内置模组string
,具体用法参考Python String。
列表
基本的列表取值上面都有说,再次不再赘述。
向列表中添加元素:
1 | list = [1, 2, 3] |
从列表中移除元素:
1 | list.pop([index=-1]) # 移除列表中的最后一个元素 |
更新列表中的元素:
1 | list[1] = 50 # 将列表中第 2 个元素值修改为 50 |
获取列表长度(元素个数):
1 | len(list) |
其他高级操作:参阅Python List。