一、常量和表达式
我们可以把 Python 当成一个计算器,来进行一些算术运算。
注意 :print 是一个 Python 内置的 函数 。可以使用 + - * / ( ) 等运算符进行算术运算, 先算乘除, 后算加减。运算符和数字之间 可以没有空格, 也可以有多个空格。 但是一般习惯上写一个空格( 美观)。
- 形如 1 + 2 - 3 这样是算式,在编程语言中称为表达式,算式的运算结果称为表达式的返回值。
- 其中 1,2,3 这种称为字面值常量,+ - * / 这种称为运算符或者操作符。
注意 : 熟悉 C / Java 就可能会认为 2 / 3 结果为 0( 小数部分被截断), 但是在 Python 中得到的结果则是一个小数, 更符合日常使用的直觉。
给定四个分数:67.5、89.0、12.9、32.2,编写代码,求这四个分数的平均数。
二、变量和类型
1、变量是什么
有的时候,我们需要进行的计算可能更复杂一些,需要把一些计算的中间结果保存起来,这个时候就需要用到变量。
给定四个分数:67.5、89.0、12.9、32.2,编写代码,求这四个分数的方差。
PS:方差的计算过程:取每一项,减去平均值(在后面的计算会被反复使用到),计算平方,再求和,最后再除以 (项数 - 1)
在这个代码中,就需要先计算这四个数字的平均值,然后再计算方差,这就需要把计算的平均值使用变量保存起来。就像计算器中的 M 键功能类似,通过变量就可以保存计算过程中的中间结果。
只不过,计算器一般只能保存一个数据,而在 Python 代码中,可以创建任意多的变量来随心所欲的保存很多很多的数据。
变量可以视为是一块能够容纳数据的空间。这个空间往往对应到 “内存” 这样的硬件设备上。
注意 :avg、total、result 均为变量。** 在 Python 中表示乘方运算, ** 2 即为求平方。
PS:可以把内存想像成是一个宿舍楼,这个宿舍楼上有很多的房间,每个房间都可以存放数据。
衡量内存的一个重要指标就是内存空间的大小,比如我的电脑内存是 16GB。这个数字越大,意味着内存的存储空间就越大,能够存放的数据(变量)就越多。
2、变量的语法
(1)定义变量
- a 为变量名。当我们创建很多个变量的时候,就可以用名字来进行区分。
- = 为赋值运算符,表示把 = 右侧的数据放到 = 左侧的空间中。
注意 : 变量的名字要遵守一定规则。
A. 硬性规则(务必遵守)
- 变量名必须由数字、字母、下划线构成,不能包含特殊符号。
- 数字不能开头。
- 变量名不能和 Python 的 “关键字”(在语法中有特定含义的)重复(比如:if、else等)。
- 变量名大小写敏感,区分大小写。num 和 Num 是两个不同的变量名。
B. 软性规则(建议遵守)
- 变量名尽量使用有描述性的单词来表示,尽量通过名字表达出变量的作用。
- 一个变量名可以由多个单词构成,变量名字长一点没有关系,但是变量的含义要清晰。
- 当变量名包含多个单词的时候,建议使用 “驼峰命名法”(除了第一个单词的首字母以外,后续每个单词的首字母都要大写),形如 totalCount,personInfo 这种。
数学上,变量通常使用 x,y,z 这种简单的英文字母或者拉丁字母表示,但是在编程中并不建议这样使用。是因为在编程中,一个程序里通常会同时创建出很多个变量。如果只是使用单个字母表示,在变量多了的时候,就很难记住每个变量对应的含义是什么,从而给维护程序带来了一定的困难,因此更建议使用带有明确描述性的名字来表示变量的用途。
(2)使用变量
A. 读取变量的值
B. 修改变量的值
注意 : 在 Python 中, 修改变量也是使用 = 运算, 看起来和定义变量没有明显区别。
当然,也可以用一个变量的值赋给另外一个变量:
首次使用 = 是对 a 进行设置值,这个过程是创建变量(初始化),后续再对 a 使用 = 操作,则是相当于修改 a 的内容赋值)。
3、变量的类型
变量里面存储的不仅仅是数字,还可以存储其它种类的数据。为了区分不同种类的数据,引入了 “类型” 这样的概念。
注意 : 和 C++ / Java 等语言不同, Python 变量的类型不需要显式指定, 而只是依靠初始化语句,根据初始化的值的类型来进行确定的。
(1)整数
type 和 print 类似,也是 python 内置的函数,可以使用 type 来查看一个变量的类型。
注意:和 C++ / Java 等语言不同,Python 的 int 类型变量,表示的数据范围是没有上限的。只要内存足够大,理论上就可以表示无限大小的数据。Python 的 int 可以根据要表示的数据的大小,自动扩容。所以,Python 就没有像 long 这样的类型,像 byte、short 这些类型也没有。
(2)浮点数(小数)
注意:和 C++ / Java 等语言不同,Python 的小数只有 float 一种类型,没有 double 类型,但实际上 Python 的 float 就相当于 C++ / Java 的 double,表示双精度浮点数。
相比于单精度浮点数,双精度浮点数占用的内存空间更多,同时表示的数据精度更高即可(大概精确到小数点后 15 位)。
(3)字符串
Python 种没有字符类型,使用 ' ' 或者 " " 引起来的称为字符串,可以用来表示文本。
注意 : 在 Python 中, 单引号构成的字符串和双引号构成的字符串, 没有区别, 'hello' 和 "hello" 是 完全等价的。如果字符串里面包含了双引号,表示字符串可以用单引号引起来;如果字符串里面包含了单引号,表示字符串可以用双引号引起来。
如果同时出现双引号或单引号呢?
Python 中还有一种字符串,使用 三引号(''' 或 """)表示。
可以使用 len 函数来获取字符串的长度:
可以使用 + 针对两个字符串进行拼接:
此处是两个字符串相加,也就是把后面的字符串拼接到前一个字符串的末尾,从而得到一个更大的字符串,对原先的 a1 和 a2 是没有影响的。
注意:不能把字符串和整数 / 浮点数进行相加。
在 Python 中,报错分以下两种情况:
- 语法错误。在程序运行之前,Python 解释器就能把错误识别出来。
- 运行错误。在程序运行之前无法识别,必须要执行到对应的代码才能发现问题。
(4)布尔
布尔类型是一个特殊的类型,取值只有两种:True(真)和 False(假)(首字母大写)。
布尔类型也是数学上的一个概念,数学上学过一个概念叫做 “命题”,进一步的就可以判定命题的真假。
(5)其他
为什么要有这么多类型?
- 类型决定了数据在内存中占据多大空间。例如:float 类型在内存中占据 8 个字节。
计算机里面使用二进制来表示数据,也就是每个位只能表示 0 或者 1。1 个二进制位就称为是一个个 “比特”,8 个二进制位,就称为一个 “字节”(Byte)。一个 float 变量在内存中占据 8 个字节空间,也就是 64 个二进制位。
假设电脑有 16GB 的内存空间,也就是一共有 1024 * 1024 * 1024 * 8 这么多的二进制位。
- 不同的类型对应能够进行的操作也是不同的。
- int / float 类型的变量,可以进行 + - * / 等操作;
- str 类型的变量,只能进行 +(并且行为是字符串拼接),但是不能进行 - * /,能够使用 len 等其他操作。
总结 : 类型系统其实是在对变量进行 “ 归类”, 相同类型的变量( 数据) 往往具有类似的特性和使用规则。
4、动态类型特性
在 Python 中,一个变量是什么类型,是可以在 “程序运行” 过程中发生变化的,这个特性称为 “动态类型”。
在程序执行过程中,a 的类型刚开始是 int,后面变成了 str,最后变成了 bool。
动态类型特性是一把双刃剑:
- 对于中小型程序,可以大大的节约代码量(比如写一段代码就可以同时支持多种类型)。
- 对于大型程序,则提高了模块之间的交互成本(A 提供的代码难以被 B 理解)。
Python 作为一个动态类型的语言,在定义变量的时候,也可以是写类型的。
C++/Java 这样的语言则不允许这样的操作。一个变量定义后类型就是固定的了,这种特性则称为 “静态类型”。
一个编程语言是否是动态类型,只取决于运行时,类型是否发生改变,不取决于变量定义的时候是否声明类型。
三、注释
1、注释是什么
注释是一种特殊的代码,它不会影响到程序的执行,但是能够起到解释说明的作用,能够帮助程序猿理解程序代码的执行逻辑。
写代码是一件比较烧脑的事情,读代码同样也非常烧脑,相比于一板一眼的代码,一些口语化的描述能更好的帮助程序猿理解程序。
形如上述代码,如果没有注释直接阅读,是不容易体会到代码的含义是计算方差,但是如果通过加了一行注释解释一下,就可以让阅读代码的人一目了然了。
代码的第一目标是容易理解,第二目标才是执行正确。
写注释不光是为了方便别人来理解,也是方便之后自己再阅读容易理解。
2、注释的语法
Python 中有两种风格的注释。
批量注释的快捷键:Ctrl + /
(1)注释行
使用 # 开头的行都是注释。
一般情况都是写在要注释的代码的上方,也有少数情况是写在要注释代码的右侧的,很少会写在代码的下方,不会写在代码的左侧。
# 这是一行注释
(2)文档字符串
- 可以包含多行内容,一般放在 文件 / 函数 / 类 的开头。
- """ 或者 ''' 均可(二者等价)。
"""
这是文档字符串
这是文档字符串
"""
3、注释的规范
- 内容准确:注释内容要和代码一致且匹配,并在代码修改迭代时及时更新调整。
- 篇幅合理:注释既不要太精简,也不要长篇大论。
- 使用中文:一般中国的公司都要求使用中文写注释,外企另当别论。
- 积极向上:注释中不要包含负能量。
四、输入输出
1、和用户交互
程序需要和用户进行交互。
- 用户把信息传递给程序的过程,称为 “输入”。
- 程序把结果展示给用户的过程,称为 “输出”。
输入输出的最基本的方法就是控制台。用户通过控制台输入一些字符串,程序再通过控制台打印出一些字符串。
PyCharm 运行程序,下方弹出的窗口就可以视为是控制台:
Windows 自带的 cmd 程序,也可以视为是控制台:
输入输出的最常见方法是图形化界面(常用)。如我们平时用到的 QQ,浏览器,steam 等,都不需要用户输入命令,而只是通过鼠标点击窗口点击按钮的方式来操作。
2、通过控制台输出
Python 使用 print 函数输出到控制台。
不仅能输出一个字符串,还可以输出一个其他类型的变量。
更多的时候,我们希望能够输出的内容是混合了字符串和变量的。示例:输出 a = 10:
注意:使用 f 作为前缀的字符串,f 表示 format,称为 f-string。里面可以使用 { } 来内嵌一个其他的变量 / 表达式。Python 中还支持其他的格式化字符串的方法。
3、通过控制台输入
python 使用 input 函数,从控制台读取用户的输入:
input 执行的时候就会等待用户输入,这个等待可能是一个非常长的等待,完全取决于用户什么时候去输入。如果用户始终不输入,那么就会一直等待。
注意:input 的参数相当于一个 “提示信息”,也可以没有。
input 的返回值就是用户输入的内容,是字符串类型。
如果只是单纯的拿到用户的输入,然后进行打印,那么此时就按照 str 打印即可。如果需要根据用户输入的内容进行算术计算,那么此时就需要先把读到的 str -> int,可以使用 int()。
此处的结果是字符串拼接,不是算术运算。如果要想进行算术运算,需要先转换类型。
通过 int( ) 把变量转成了 int 类型。
使用 float( )(将字符串转换成浮点数)、bool( ),str( )(将整数转换成字符串)等可以完成对应的类型转换。
代码示例:输入 4 个小数,求 4 个小数的平均值。
五、运算符
1、算术运算符
像 + - * / % ** // 这种进行算术运算的运算符,称为算术运算符。
注意:/ 中不能用 0 作为除数,否则会抛出异常。
有些编程语言中,/ 整数 0 会抛出异常,/ 浮点数 0 会得到无穷大,而在 Python 中则都认为是除 0 异常。
异常是编程语言中的一种常见机制,表示程序运行过程中,出现了一些 “意外情况”,导致程序不能继续往下执行了。
先算乘方,再算乘除,最后算加减。如果在运算过程中想要修改默认的运算顺序,就需要加上()。
注意 :整数 / 整数 结果可能是小数,而不会截断。
关于求余数:7 除以 2,商是 3,余数是 1。
% 不是 “百分数”,而是求余数。得到的余数一定是小于除数的。
** 是求乘方。既能算整数次方,还能算小数次方(开方运算)。
// 是取整除法(也叫地板除)。整数除以整数,结果还是整数(舍弃小数部分,并向下取整,不是四舍五入)。
2、关系运算符
- <= 是 “小于等于”
- >= 是 “大于等于”
- == 是 “等于”
- != 是 “不等于”
(1)关系运算符对应的表达式的值是布尔类型
如果关系符合要求,则表达式返回 True;如果关系不符合要求,则表达式返回 False。
(2)关系运算符不光针对整数 / 浮点数进行比较,还能针对字符串进行比较
注意 :直接使用 == 或者 != 即可对字符串内容判定相等( 这一点和 C / Java 不同)。 字符串比较大小, 规则是 “ 字典序” 。
针对中文进行字符串大小的比较是没有意义的,至少按照默认的字典序来说是没有意义的。在计算机中表示中文,其实是多个字节构成的一个比较大的数字来进行比较。
- 在 C/C++ 中,strcmp,如果直接使用 ==,本质上是在比较两个字符串首元素的地址。
- 在 Java 中,equals 方法,如果使用 ==,本质上是在比较这两个字符串是否为同一个对象。
Python 是直接使用 == 和 != 来比较字符串内容相同,这是大部分编程语言遵守的规则。
(3)对于浮点数来说,不要使用 == 判定相等
注意 : 浮点数在计算机中的表示并不是精确的,因为浮点数在内存中的存储和表示是可能存在误差的。这样的误差在进行运算过程中就可能被放大,从而导致出现误判 。
可以看到,0.1 + 0.2 的结果并非是 0.3,虽然这两个数字已经非常接近了,但是如果使用 == 进行比较,仍然会导致 == 的结果为 False。
不止是 Python 如此,主流编程语言都是如此。这个是 IEEE754 标准规定的浮点数格式所引入的问题。
正确的比较方式:不再严格比较相等了,而是判定差值小于允许的误差范围。
在 Python 中支持这种连续小于的写法,判断 a-b 既是 > -0.000001 又是 < 0.000001。
实际工程实践中,误差在所难免,只要保证误差在合理范围内即可。
3、逻辑运算符
像 and or not 这一系列的运算符称为逻辑运算符。
- and:并且,两侧操作数均为 True,最终结果为 True,否则为 False(一假则假)
- or:或者,两侧操作数均为 False,最终结果为 False,否则为 True(一真则真)
- not:逻辑取反,操作数本身为 True,则返回 False,本身为 False,则返回 True。
此处说的 “并且” 和 “或者”,就是平时日常生活中使用的 “并且” 和 “或者”。
(1)一种特殊的写法
a < b and b < c 这个操作等价于 a < b < c
(2)短路求值
- 对于 and,如果左侧表达式为 False,则整体一定为 False,右侧表达式不再执行。
- 对于 or,如果左侧表达式为 True,则整体一定为 True,右侧表达式不再执行。
上述代码没有抛出异常,说明右侧的除以 0 操作没有真正执行。
4、赋值运算符
(1)= 的使用
= 表示赋值,已经用过很多次了,注意和 == 做区分。
= 除了基本的用法之外,还可以同时针对多个变量进行赋值。
A. 链式赋值
a = b = 10
# 先把 10 赋值给 b
# 再把 b 赋值给 a
一般不建议使用链式赋值,尽量一行代码只是包含一个操作。
B. 多元赋值
a, b = 10, 20
# 把 10 赋值给 a
# 把 20 赋值给 b
交换两个变量:
基于多元赋值:
(2)复合赋值运算符
Python 还有一些 复合赋值运算符,例如 += -= *= /= %=。
其中 a += 1 等价于 a = a + 1,其他复合赋值运算符也是同理。
注意 : 像 C++ / Java 中, 存在 ++ -- 这样的自增 / 自减运算符, Python 中则不支持这种运算。 如果需要使用,则直接使用 += 1 或者 - = 1。
++ 和 -- 最大的问题就是容易分不清前置和后置的区别,这一点 Python 语法在设计的时候就进行了规避,避免出现这种不直观,并且容易混淆的语法。
5、其他
除了上述之外,Python 中还有一些运算符,比如身份运算符(is,is not),成员运算符(in,not in),位运算符(& | ~ ^ << >>)等,这里暂时不做介绍。