Python - 100天从新手到大师

Python - 100天从新手到大师
Penry引言
这里主要是依托于 jackfrued
仓库 Python-100-Days 进行学习,记录自己的学习过程和心得体会。
Day1 - 初识 Python
1 Python 简介
Python(英式发音:/ˈpaɪθən/;美式发音:/ˈpaɪθɑːn/)是由荷兰人吉多·范罗苏姆(Guido von Rossum)发明的一种编程语言,是目前世界上最受欢迎和拥有最多用户的编程语言。Python 强调代码的可读性和语法的简洁性,相较于 C、C++、Java 这些同样影响深远的编程语言,Python 让使用者能够用更少的代码表达自己的意图。下面是几个权威的编程语言排行榜给出的 Python 语言的排名,其中第1张图由 TIOBE Index 提供,第3张图由 IEEE Spectrum 提供。值得一提的是第2张图,它展示了编程语言在全球最大代码托管平台 GitHub 上受欢迎的程度,最近的四年时间 Python 语言都占据了冠军的宝座。
1.1 Python 编年史
-
1989年
- 荷兰程序员吉多·范罗苏姆在圣诞假期开始开发新编程语言
- 名称源自喜剧《Monty Python’s Flying Circus》
-
1991年
- 2月20日发布Python 0.9.0
- 首次具备类继承、异常处理等现代特性
- 确立"Batteries included"哲学
-
1994年
- Python 1.0发布
- 引入函数式编程工具
lambda
,map
,filter
- 形成开源社区雏形
-
2000年
- Python 2.0发布
- 新增垃圾回收机制
- 标准库突破2万个函数
- Zope成为首个企业级Python产品
-
2003年
- NumPy库发布
- 科学计算领域开始大规模采用
- NASA、劳伦斯国家实验室成为早期用户
-
2008年
- Python 3.0(代号Py3K)发布
- 核心革新:统一Unicode编码,print改为函数
- 向后不兼容引发社区长期讨论
-
2010年
- Flask框架诞生
- PyPI仓库突破1万个软件包
- Instagram全面转向Python技术栈
-
2013年
- Pandas 0.12重塑数据处理标准
- Jupyter Notebook成为科研标配
- Netflix推荐系统Python化
-
2016年
- TensorFlow 1.0确立AI框架标准
- Python占据91%机器学习框架市场
- RedMonk语言排行榜首次登顶
-
2019年
- Python 2.7正式退役
- 结束长达10年的2.x/3.x并行期
-
2020年
- Python 3.9发布
- 引入模式匹配(match/case)
- 官方支持Mypy静态类型检查
-
2021年
- Python 3.10推出结构化模式匹配
- 语言创建者吉多·范罗苏姆加入微软
- 社区启动解释器性能优化计划
-
2022年
- Python 3.11发布
- 解释器速度平均提升25%
- 引入Exception Groups语法
- TIOBE年度语言冠军
-
2024年
- Python 3.12引入JIT编译器雏形
- 全球用户突破2500万
- 教育领域采用率达87%
- 持续主导AI大模型开发
1.2 Python优缺点
Python 语言的优点很多,简单为大家列出几点。
- 简单优雅,跟其他很多编程语言相比,Python 更容易上手。
- 能用更少的代码做更多的事情,提升开发效率。
- 开放源代码,拥有强大的社区和生态圈。
- 能够做的事情非常多,有极强的适应性。
- 胶水语言,能够黏合其他语言开发的东西。
- 解释型语言,更容易跨平台,能够在多种操作系统上运行。
Python 最主要的缺点是执行效率低(解释型语言的通病),如果更看重代码的执行效率,C、C++ 或 Go 可能是你更好的选择。
1.2 安装 Python 环境
建议直接使用 Anaconda 配置环境,Anaconda 是一个开源的 Python 发行版,它包含了大量的科学计算库,同时它还提供了一个包管理器和环境管理器,可以方便地安装和管理 Python 包和环境。
这里我给出一些参考链接:
2 Python 语言中的变量
对于想学习编程的新手来说,有两个问题可能是他们很想知道的,其一是“什么是(计算机)程序”,其二是“写(计算机)程序能做什么”。先说说我对这两个问题的理解:程序是数据和指令的有序集合,写程序就是用数据和指令控制计算机做我们想让它做的事情。今时今日,为什么有那么多人选择用 Python 语言来写程序,因为 Python 语言足够简单和强大。相较于 C、C++、Java 这样的编程语言,Python 对初学者和非专业人士更加友好,很多问题在 Python 语言中都能找到简单优雅的解决方案。接下来,我们就从最基础的语言元素开始,带大家认识和使用 Python 语言。
2.1 一些常识
在开始系统的学习 Python 编程之前,我们先来科普一些计算机的基础知识。计算机的硬件系统通常由五大部件构成,包括:运算器、控制器、存储器、输入设备和输出设备。其中,运算器和控制器放在一起就是我们常说的中央处理器(CPU),它的功能是执行各种运算和控制指令。刚才我们提到过,程序是指令的集合,写程序就是将一系列的指令按照某种方式组织到一起,然后通过这些指令去控制计算机做我们想让它做的事情。存储器可以分为内部存储器和外部存储器,前者就是我们常说的内存,它是中央处理器可以直接寻址的存储空间,程序在执行的过程中,对应的数据和指令需要加载到内存中。输入设备和输出设备经常被统称为 I/O 设备,键盘、鼠标、麦克风、摄像头是典型的输入设备,而显示器、打印机、扬声器等则是典型的输出设备。目前,我们使用的计算机基本大多是遵循“冯·诺依曼体系结构”的计算机,这种计算机有两个关键点:一是将存储器与中央处理器分开;二是将数据以二进制方式编码。
二进制是一种“逢二进一”的计数法,跟人类使用的“逢十进一”的计数法本质是一样的。人类因为有十根手指,所以使用了十进制计数法,在计数时十根手指用完之后,就只能用进位的方式来表示更大的数值。当然凡事都有例外,玛雅人可能是因为长年光着脚的原因,把脚趾头也都用上了,于是他们使用了二十进制的计数法。基于这样的计数方式,玛雅人使用的历法跟我们平常使用的历法就产生了差异。按照玛雅人的历法,2012 年是上一个所谓的“太阳纪”的最后一年,而 2013 年则是新的“太阳纪”的开始。后来这件事情还被以讹传讹的方式误传为“2012 年是玛雅人预言的世界末日”的荒诞说法。今天有很多人猜测,玛雅文明之所以发展缓慢跟使用了二十进制是有关系的。对于计算机来说,二进制在物理器件上最容易实现的,因为可以用高电压表示 1,用低电压表示 0。不是所有写程序的人都需要熟悉二进制,熟悉十进制与二进制、八进制、十六进制的转换,大多数时候我们即便不了解这些知识也能写程序。但是,我们必须知道,计算机是使用二进制计数的,不管什么样的数据,到了计算机内存中都是以二进制形态存在的。
说明:关于二进制计数法以及它与其他进制如何相互转换,大家可以翻翻名为《计算机导论》或《计算机文化》的书,都能找到相应的知识,此处就不再进行赘述了,不清楚的读者可以自行研究。
2.2 变量和类型
要想在计算机的内存中保存数据,首先得说一说变量这个概念。在编程语言中,变量是数据的载体,简单的说就是一块用来保存数据的内存空间,变量的值可以被读取和修改,这是所有运算和控制的基础。计算机能处理的数据有很多种类型,最常见的就是数值,除了数值之外还有文本、图像、音频、视频等各种各样的数据类型。虽然数据在计算机中都是以二进制形态存在的,但是我们可以用不同类型的变量来表示数据类型的差异。Python 语言中预设了多种数据类型,也允许我们自定义新的数据类型,这一点在后面会讲到。我们首先来了解几种 Python 中最为常用的数据类型。
- 整型(
int
):Python 中可以处理任意大小的整数,而且支持二进制(如0b100
,换算成十进制是4)、八进制(如0o100
,换算成十进制是64)、十进制(100)和十六进制(0x100
,换算成十进制是256)的表示法。运行下面的代码,看看会输出什么。
1 | print(0b100) # 二进制整数 |
- 浮点型(
float
):浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,浮点数除了数学写法(如123.456)之外还支持科学计数法(如1.23456e2,表示)。运行下面的代码,看看会输出什么。
1 | print(123.456) |
- 字符串型(
str
):字符串是以单引号或双引号包裹起来的任意文本,比如’hello’和"hello"。
1 | print('hello') |
- 布尔型(
bool
):布尔型只有True、False两种值,要么是True,要么是False,可以用来表示现实世界中的“是”和“否”,命题的“真”和“假”,状况的“好”与“坏”,水平的“高”与“低”等等。如果一个变量的值只有两种状态,我们就可以使用布尔型。
1 | print(int(True)) |
2.3 变量命名
对于每个变量,我们都需要给它取一个名字,就如同我们每个人都有自己的名字一样。在 Python 中,变量命名需要遵循以下的规则和惯例。
- 规则部分:
- 规则1:变量名由字母、数字和下划线构成,数字不能开头。需要说明的是,这里说的字母指的是 Unicode 字符,Unicode 称为万国码,囊括了世界上大部分的文字系统,这也就意味着中文、日文、希腊字母等都可以作为变量名中的字符,但是一些特殊字符(如:!、@、#等)是不能出现在变量名中的。我们强烈建议大家把这里说的字母理解为尽可能只使用英文字母。
- 规则2:Python 是大小写敏感的编程语言,简单的说就是大写的A和小写的a是两个不同的变量,这一条其实并不算规则,而是需要大家注意的地方。
- 规则3:变量名不要跟 Python 的关键字重名,尽可能避开 Python 的保留字。这里的关键字是指在 Python 程序中有特殊含义的单词(如:
is
、if
、else
、for
、while
、True
、False
等),保留字主要指 Python 语言内置函数、内置模块等的名字(如:int
、print
、input
、str
、math
、os
等)。
- 惯例部分:
- 惯例1:变量名应该具有可读性,能够反映出变量的含义,比如一个表示年龄的变量,我们就可以命名为
age
,而不是a
或者x
。 - 惯例2:变量名应该避免使用缩写,除非缩写非常常见且易于理解,比如
name
比nm
要好,age
比a
要好。 - 惯例3:变量名通常使用小写英文字母,多个单词用下划线进行连接。
- 惯例4:受保护的变量用单个下划线开头。
- 惯例5:私有的变量用两个下划线开头。
- 惯例1:变量名应该具有可读性,能够反映出变量的含义,比如一个表示年龄的变量,我们就可以命名为
2.4 变量的使用
下面通过例子来说明变量的类型和变量的使用。
1 | """ |
在 Python 中可以使用type
函数对变量的类型进行检查。程序设计中函数的概念跟数学上函数的概念非常类似,数学上的函数相信大家并不陌生,它包括了函数名、自变量和因变量。如果暂时不理解函数这个概念也不要紧,我们会在后续的内容中专门讲解函数的定义和使用。
1 | """ |
可以通过 Python 内置的函数来改变变量的类型,下面是一些常用的和变量类型相关的函数。
int()
:将一个数值或字符串转换成整数,可以指定进制。float()
:将一个字符串(在可能的情况下)转换成浮点数。str()
:将指定的对象转换成字符串形式,可以指定编码方式。chr()
:将整数(字符编码)转换成对应的(一个字符的)字符串。ord()
:将(一个字符的)字符串转换成对应的整数(字符编码)。
下面的例子为大家演示了 Python 中类型转换的操作。
1 | """ |
说明:
str
类型转int
类型时可以通过base
参数来指定进制,可以将字符串视为对应进制的整数进行转换。str
类型转成bool
类型时,只要字符串有内容,不是’'或"",对应的布尔值都是True
。bool
类型转int
类型时,True
会变成1,False
会变成0。在 ASCII 字符集和 Unicode 字符集中, 字符'd'
对应的编码都是100
。
3 Python语言中的运算符
Python 语言支持很多种运算符,下面的表格按照运算符的优先级从高到低,对 Python 中的运算符进行了罗列。有了变量和运算符,我们就可以构造各种各样的表达式来解决实际问题。在计算机科学中,表达式是计算机程序中的句法实体,它由一个或多个常量、变量、函数和运算符组合而成,编程语言可以对其进行解释和计算以得到另一个值。不理解这句话没有关系,但是一定要知道,不管使用什么样的编程语言,构造表达式都是非常重要的。
运算符 | 描述 |
---|---|
[] 、[:] |
索引、切片 |
** |
幂 |
~ 、+ 、- |
按位取反、正号、负号 |
* 、/ 、% 、// |
乘、除、模、整除 |
+ 、- |
加、减 |
>> 、<< |
右移、左移 |
& |
按位与 |
^ 、| |
按位异或、按位或 |
<= 、< 、> 、>= |
小于等于、小于、大于、大于等于 |
== 、!= |
等于、不等于 |
is 、is not |
身份运算符 |
in 、not in |
成员运算符 |
not 、or 、and |
逻辑运算符 |
= 、+= 、-= 、*= 、/= 、%= 、//= 、**= 、&= 、\|= 、^= 、>>= 、<<= |
赋值运算符 |
说明: 所谓优先级就是在一个运算的表达式中,如果出现了多个运算符,应该先执行什么再执行什么的顺序。编写代码的时候,如果搞不清楚一个表达式中运算符的优先级,可以使用圆括号(小括号)来确保运算的执行顺序。
3.1 算术运算符
Python 中的算术运算符非常丰富,除了大家最为熟悉的加、减、乘、除之外,还有整除运算符、求模(求余数)运算符和求幂运算符。下面的例子为大家展示了算术运算符的使用。
1 | """ |
算术运算需要先乘除后加减,这一点跟数学课本中讲的知识没有区别,也就是说乘除法的运算优先级是高于加减法的。如果还有求幂运算,求幂运算的优先级是高于乘除法的。如果想改变算术运算的执行顺序,可以使用英文输入法状态下的圆括号(小括号),写在圆括号中的表达式会被优先执行,如下面的例子所示。
1 | """ |
3.2 赋值运算符
赋值运算符应该是最为常见的运算符,它的作用是将右边的值赋给左边的变量。赋值运算符还可以跟上面的算术运算符放在一起,组合成复合赋值运算符,例如:a += b
相当于a = a + b
,a *= a + 2
相当于a = a * (a + 2)
。下面的例子演示了赋值运算符和复合赋值运算符的使用。
1 | """ |
赋值运算构成的表达式本身不产生任何值,也就是说,如果你把一个赋值表达式放到print
函数中试图输出表达式的值,将会产生语法错误。为了解决这个问题,Python 3.8 中引入了一个新的赋值运算符:=
,我们称之为海象运算符,大家可以猜一猜它为什么叫这个名字。海象运算符也是将运算符右侧的值赋值给左边的变量,与赋值运算符不同的是,运算符右侧的值也是整个表达式的值,看看下面的代码大家就明白了。
- 这里给出一个海象运算符的详细介绍文档:Python 海象运算符
1 | """ |
提示:上面第 8 行代码如果不注释掉,运行代码会看到
SyntaxError: invalid syntax
错误信息,注意,这行代码中我们给a = 10
加上了圆括号,如果不小心写成了print(a = 10)
,会看到TypeError: 'a' is an invalid keyword argument for print()
错误信息,后面讲到函数的时候,大家就会明白这个错误提示是什么意思了。
这里给出一个普通赋值运算符和海象运算符实现密码输入检验程序的对比:
1 | """ |
1 | """ |
3.3 比较运算符和逻辑运算符
比较运算符也称为关系运算符,包括==
、!=
、<
、>
、<=
、>=
,我相信大家一看就能懂。需要提醒的是比较相等用的是==
,请注意这里是两个等号,因为=
是赋值运算符,我们在上面刚刚讲到过。比较不相等用的是!=
,跟数学课本中使用的并不相同,Python 2 中曾经使用过<>
来表示不等于,在 Python 3 中使用<>
会引发SyntaxError
(语法错误)。比较运算符会产生布尔值,要么是True
,要么是False
。
逻辑运算符有三个,分别是and
、or
和not
。and
字面意思是“而且”,所以and
运算符会连接两个布尔值或者产生布尔值的表达式,如果两边的布尔值都是True
,那么运算的结果就是True
;左右两边的布尔值有一个是False
,最终的运算结果就是False
。注意,如果and
运算符左边的布尔值是False
,不管右边的布尔值是什么,最终的结果都是False
,这时运算符右边的布尔值会被跳过(专业的说法叫短路处理,如果and
右边是一个表达式,那么这个表达式不会执行)。or
字面意思是“或者”,所以or
运算符也会连接两个布尔值或产生布尔值的表达式,如果两边的布尔值有任意一个是True
,那么最终的结果就是True
。注意,or
运算符也是有短路功能的,当它左边的布尔值为True
的情况下,右边的布尔值会被短路(如果or
右边是一个表达式,那么这个表达式不会执行)。not
运算符的后面可以跟一个布尔值,如果not
后面的布尔值或表达式是True
,那么运算的结果就是False
;如果not
后面的布尔值或表达式是False
,那么运算的结果就是True
。
1 | """ |
说明:比较运算符的优先级高于赋值运算符,所以上面的
flag0 = 1 == 1
先做1 == 1
产生布尔值True
,再将这个值赋值给变量flag0
。,
进行分隔,输出的内容默认以空格分开。
思考以下问题并与结果对比:
1 | """ |
1 | """ |
这里在测试过程中发现我们还需要详细学习一下 and
和 or
返回值规则:
and
返回值规则:- 如果 左操作数为假值 → 直接返回左操作数
- 如果 左操作数为真值 → 直接返回右操作数(无论右操作数的真假)
or
返回值规则:- 如果 左操作数为真值 → 直接返回左操作数
- 如果 左操作数为假值 → 直接返回右操作数(无论右操作数的真假)
1 | """ |
3.4 运算符和表达式应用
例子1:华氏温度转摄氏温度
要求:输入华氏温度将其转换为摄氏温度,华氏温度到摄氏温度的转换公式为: 。
1 | """ |
说明:上面代码中的
input
函数用于从键盘接收用户输入,由于输入的都是字符串,如果想处理成浮点小数来做后续的运算,可以用我们上一课讲解的类型转换的方法,用float
函数将str
类型处理成float
类型。
上面的代码中,我们对print
函数输出的内容进行了格式化处理,print
输出的字符串中有两个%.1f
占位符,这两个占位符会被%
之后的(f, c)
中的两个float
类型的变量值给替换掉,浮点数小数点后保留1位有效数字。如果字符串中有%d
占位符,那么我们会用int
类型的值替换掉它,如果字符串中有%s
占位符,那么它会被str
类型的值替换掉。
除了上面格式化输出的方式外,Python 中还可以用下面的办法来格式化输出,我们给出一个带占位符的字符串,字符串前面的f
表示这个字符串是需要格式化处理的,其中的{f:.1f}
和{c:.1f}
可以先看成是{f}
和{c}
,表示输出时会用变量f
和变量c
的值替换掉这两个占位符,后面的:.1f
表示这是一个浮点数,小数点后保留1位有效数字。
1 | """ |
例子2:计算圆的周长和面积
要求:输入一个圆的半径(),计算出它的周长( )和面积( )。
1 | """ |
Python 中有一个名为math
的内置模块,该模块中定义了名为pi
的变量,它的值就是圆周率。如果要使用 Python 内置的这个pi
,我们可以对上面的代码稍作修改。
1 | """ |
说明:上面代码中的
import math
表示导入math
模块,导入该模块以后,才能用math.pi
得到圆周率的值。
这里其实还有一种格式化输出的方式,是 Python 3.8 中增加的新特性,大家直接看下面的代码就明白了。
1 | """ |
说明:假如变量
a
的值是9.87
,那么字符串f'{a = }'
的值是a = 9.87
;而字符串f'{a = :.1f}'
的值是a = 9.9
。这种格式化输出的方式会同时输出变量名和变量值。
例子3:判断闰年
要求:输入一个 1582 年以后的年份,判断该年份是不是闰年。
1 | """ |
说明:对于格里历(Gregorian calendar),即今天我们使用的公历,判断闰年的规则是:1. 公元年份非 4 的倍数是平年;2. 公元年份为 4 的倍数但非 100 的倍数是闰年;3. 公元年份为 400 的倍数是闰年。格里历是由教皇格里高利十三世在 1582 年 10 月引入的,作为对儒略历(Julian calendar)的修改和替代,我们在输入年份时要注意这一点。上面的代码通过
%
来判断year
是不是4
的倍数、100
的倍数、400
的倍数,然后用and
和or
运算符将三个条件组装在一起,前两个条件要同时满足,第三个条件跟前两个条件的组合只需满足其中之一。