Python教学【第二课】

Python基础:数据类型

我们来看这么一段代码,并运行他:

x = 10
y = "10"
z = 10.0
print(x + x, type(x)) # 20 <class 'int'>
print(y + y, type(y)) # 1010 <class 'str'>
print(z + z, type(z)) # 20.0 <class 'float'>

通过分析运行过程,上面声明了三种不同数据类型下10的变量,我们可以看到,不同类型的数据类型相加产生不一样的结果:

  1. x 是整数型 int -> integer,相加之后值为整形20
  2. y 是字符串型 str -> string,相加之后值为字符串”1010”,这就是字符串拼接
  3. z 是浮点型 float,相加之后值为浮点型20.0

Python解释器

Python的解释器(Python Interpreter)是个很强大的功能。它能够实时的将您所输入的代码反馈到终端界面上,让您查看这段代码的执行结果。事实上,在Python解释器中所输入的Python语句都能在代码里写出来。

在终端输入python即可进入python解释器中(前提是你得在安装python过程中勾选Add to Path选项)。这时,您的终端界面应该长这样:

C:\Users\username>python
Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

进行数学运算

进入解释器之后,我们可以在>>>之后写入我们的python语法,我们试试输入几个简单的数学公式。每输入一个公式之后,解释器会直接写出答案:

python支持多种数学运算符,+ - * /只是其中几个,我们将在后续课程进行讲解;()符对公式进行分组。和数学一样,python也遵循”先乘除,后加减”的运算原则,所以我们需要通过括号对某些公式的优先级进行分组。

/一定返回一个浮点数,如果结果只是要获得一个整数,可以使用//运算分;我们也可以使用%计算余数

**用来计算乘方

=用于给变量赋值,赋值不会有结果显示出来

>>> 50 - 5*6
20
>>> (50 - 5*6) / 4
5.0
>>> 17 / 3 # 普通的除法返回一个浮点数
5.666666666666667
>>> 17 // 3 # 底数分割丢弃小数部分
5
>>> 17 % 3 # %运算符返回除法的余数
2
>>> 5 ** 2 # 5的平方
25
>>> 2 ** 7 # 2的7次幂
128
>>> width = 20
>>> height = 5 * 9
>>> width * height
900

如果访问一个没有定义(未赋值)的变量,尝试访问它时就会报错。

>>> n  # 尝试访问一个未初始化的变量
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'n' is not defined

上一次打印出来的值会被保存在变量_,你可以通过访问变量_继续使用这个值。
注意:这个变量是只读的,不要尝试向他赋值

>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06

字符串

使用单引号'... ...'或双引号"... ..."包含起来的一串字符称为字符串,\可以用来转义;输出的字符串会加上引号,print()函数会生成可读性更强的输出,即略去两边的引号,并且打印出经过转义的特殊字符:

>>> 'spam eggs'  # 用单引号包含
'spam eggs'
>>> 'doesn\'t' # 用 '\' 来转义单引号
"doesn't"
>>> "doesn't" # 用双引号包含,中间的单引号就不需要转义
"doesn't"
>>> '"Yes," they said.'
'"Yes," they said.'
>>> "\"Yes,\" they said."
'"Yes," they said.'
>>> '"Isn\'t," they said.'
'"Isn\'t," they said.'
>>> print('"Isn\'t," they said.')
"Isn't," they said.
>>> s = 'First line.\nSecond line.' # \n 是换行
>>> s # 没有调用print函数,\n 包含在输出里
'First line.\nSecond line.'
>>> print(s) # 调用print(), \n 转译成换行
First line.
Second line.

如果不希望前置\的字符被转义,可以使用原始字符串模式,在引号前面加上r

>>> print('C:\some\name')  # \s 无意义,但 \n 是换行
C:\some
ame
>>> print(r'C:\some\name') # 加上r之后,\n不再被转译成换行
C:\some\name

第一堂课我们提到了多行字符串的输入,也就是三个单引号'''...'''或三个双引号"""...""",字符串的回车会直接包含在字符串中,如果不想要包含该行的回车,可以用\跳过:

print("""\ # 如果不加上反斜杠,这里将输出个换行
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
""")
# 输出(注意最开始的换行没有被包含进来)
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to

我们学会了+能够连接两个字符串,那么*可以对字符串进行重复;两个相邻的字符串也将会自动连接在一起,把很长的字符串拆开分别输入的时候尤其有用:

>>> 3 * "un" + "ium" "Py" "thon" # 注意字符串的输出
unununiumPython
>>> text = ('将多个字符串放在括号中'
... '以使它们连接在一起。')
>>> text
'将多个字符串放在括号中以使它们连接在一起。'

但是字符串的自动相连只能对两个字面值这么做,变量或表达式不行,如果想链接变量或表达式,可以用+,但前提是被连接的必须是字符串:

>>> prefix = 'Py'
>>> prefix 'thon' # can't concatenate a variable and a string literal
File "<stdin>", line 1
prefix 'thon'
^
SyntaxError: invalid syntax
>>> ('un' * 3) 'ium'
File "<stdin>", line 1
('un' * 3) 'ium'
^
SyntaxError: invalid syntax

字符串是可以被 索引 (下标访问)的,第一个字符索引是 0。单个字符并没有特殊的类型,只是一个长度为一的字符串;索引也可以用负数,这种会从右边开始数:

>>> word = 'Python'
>>> word[0] # 第0位字符
'P'
>>> word[5] # 第五位字符
'n'
>>> word[-1] # 最后一个字符
'n'
>>> word[-2] # 最后第二个字符
'o'
>>> word[-6]
'P'

除了索引,字符串还支持 切片。索引可以得到单个字符,而 切片 可以获取子字符串,切片的开始总是被包括在结果中,而结束不被包括。这使得 s[:i] + s[i:] 总是等于 s;切片的索引有默认值:省略开始索引时默认为0,省略结束索引时默认为到字符串的结束

>>> word[0:2]  # characters from position 0 (included) to 2 (excluded)
'Py'
>>> word[2:5] # characters from position 2 (included) to 5 (excluded)
'tho'
>>> word[:2] + word[2:]
'Python'
>>> word[:4] + word[4:]
'Python'
>>> word[:2] # character from the beginning to position 2 (excluded)
'Py'
>>> word[4:] # characters from position 4 (included) to the end
'on'
>>> word[-2:] # characters from the second-last (included) to the end
'on'

您也可以这么理解切片:将索引视作指向字符 之间 ,第一个字符的左侧标为0,最后一个字符的右侧标为 n ,其中 n 是字符串长度。例如:

 +---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1

第一行数标注了字符串非负的索引的位置,第二行标注了对应的负的索引。那么从 ij 的切片就包括了标有 ij 的位置之间的所有字符。

对于使用非负索引的切片,如果索引不越界,那么得到的切片长度就是起止索引之差。例如, word[1:3] 的长度为2.

使用过大的索引会产生一个错误(数组越界),但是,切片中的越界索引会被自动处理::

>>> word[42]  # the word only has 6 characters
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range

>>> word[4:42]
'on'
>>> word[42:]
''

Python 中的字符串不能被修改,它们是不可变的。因此,向字符串的某个索引位置赋值会产生一个错误:

>>> word[0] = 'J'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> word[2:] = 'py'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

如果需要一个不同的字符串,应当新建一个:

>>> 'J' + word[1:]
'Jython'
>>> word[:2] + 'py'
'Pypy'

内建函数 len()返回一个字符串的长度:

>>> s = 'supercalifragilisticexpialidocious'
>>> len(s)
34

这只是字符串的其中一部分,后续会通过实例等讲解更多字符串的用法

列表(List)

Python里的数组叫做列表(个别教程上也叫他序列),它的定义方式是这样的:

alist = [1, 3, 5, 7, 9] # 这个alist列表将会贯彻接下来这个单元的教程

和字符串一样(实际上字符串可以理解为一个数组),列表里面的元素也可以通过下标来访问。当然也包括切片(Slices)

name = "Xiaomai"
print(name[3], alist[3]) # o 7
print(alist[-1]) # 9 最后一个元素
print(alist[2:]) # [5, 7, 9] 第二个元素开始到最后一个
print(alist[:2]) # [1, 3] 第一个元素开始到第二个

跟字符串很相似,使用+运算符可以拼接列表

alist += [2, 4, 6, 8, 10]
print(alist) # [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]

和字符串不一样的是:列表的元素可以被改变

alist[5] = 11
print(alist) # [1, 3, 5, 7, 9, 11, 4, 6, 8, 10]

Index函数:我们可以用list的index函数找到某个元素的下标:比如我们需要替换alist列表里值为11的元素,可以通过这行代码。但是Index参数里的数据值没有出现在列表里,则会报错

alist[alist.index(4)] = 13 # 等价于:alist[6] = 13
print(alist) # [1, 3, 5, 7, 9, 11, 13, 6, 8, 10]
alist.index(22) # ValueError: 22 is not in list

Append函数:用于在数组末尾添加元素

alist.append(666)
print(alist) # [1, 3, 5, 7, 9, 11, 13, 6, 8, 10, 666]
alist.append([6, 6, 6])
print(alist) # [1, 3, 5, 7, 9, 11, 13, 6, 8, 10, 666, [6, 6, 6]]

从上面的例子可以知道,list的元素可以包含不止一种数据类型

利用切片,我们也可以对列表的某一个片段的值进行增加、修改、删除等操作。或者直接清空整个列表。这个过程不会“创建”新的列表实例(进阶教学里解释)

alist = ["Apple", "Ball", "Covid", "Donkey", "Egg", "Food"] # 重新初始化数组
alist[2:5] = ["Graph", "Hello", "Igloo"] # 原先三个,替换三个
alist[2:5] = ["Joker", "Knight"] # 原先三个,替换两个 -> 少一个
alist[2:5] = ["Light", "Monkey", "Nurse", "Order"] # 原先三个,替换四个 -> 多一个
alist[2:5] = [] # 清空这段切片的元素
alist[:] = [] # 清空整个列表,用的是旧的列表实例