大学数学有一门基础课叫线性代数,其中有一个基础知识点就是:矩阵。最简单理解就是一堆有关联的数值,我们可以对其进行某种运算,如加减乘除等。
高中数学有数列这个知识点,就是按照一定次序排序的一列数;还有排列和组合,都是讲一堆数,怎么去发现其关联关系,怎么对它施加各种运算。
计算机既然来源于数学,解决数学中一些计算问题,对上面讲的知识点也就有一个解决的知识点,那就是数组。
C,C++,Java等语言里是直接有数组这个数据结构的,而且是语言直接原生支持。Python与众不同,没有直接叫数组的定义,而是叫序列类型Sequence Types: list, tuple, range。
list是可修改的序列,tuple是不可修改的序列,range是一个不可修改的数值序列,主要是给for循环使用的。
list是一个可修改的序列,有4种方式来创建一个序列:
1)空序列:
s = []
2)用常量或变量来初始化一个序列:
s1 = [1]
s2 = ['a', 'b', 'c']
s3 = [a, b, c]
3)使用一个迭代器来创建一个序列:
s = [x for x in iterable]
上面的iterable是一个迭代器,后面会讲到,暂时知道有这么一个情况就行。
4)用语言内置函数list来定义:
s1 = list()
s2 = list(iterable)
学习编程知识点,随时来一段代码验证:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 练习List
def main():
s1 = []
print(s1)
s2 = [1]
print(s2)
s3 = [1, 2, 3]
print(s3)
s4 = [x for x in [4, 5, 6, 7]]
print(s4)
s5 = list()
print(s5)
s6 = list(['a', 'b'])
print(s6)
if __name__ == '__main__':
main()
tuple是一个不可修改的序列,也有4种方式来创建:
1)空序列:
t = ()
2)用一个逗号来创建单个值的序列:
t1 = a,
t2 = (a,)
3)用多个逗号来创建序列:
t1 = a, b, c
t2 = (a, b, c)
4)使用内置函数tuple()来创建序列:
t1 = tuple()
t2 = tuple(iterable)
学习编程知识点,随时来一段代码验证:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 练习Tuple
def main():
t1 = ()
print(t1)
t2 = 1,
print(t2)
t3 = (2,)
print(t3)
t4 = 1, 2, 3
print(t4)
t5 = (1.1, 1.2, 1.3)
print(t5)
t6 = tuple()
print(t6)
t7 = tuple([4, 5])
print(t7)
for method in dir(tuple):
print(method)
if __name__ == '__main__':
main()
range类型是一个不可修改的序列类型,主要给for循环提供一个步长操作的。
它的初始化只有2种:
x1 = range(stop)
x2 = range(start, stop, [, step])
不指定start, 默认start是0, 不指定step,默认step是1。
学习编程知识点,随时来一段代码验证:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 练习range
def main():
x1 = range(10)
for n in x1:
print(n)
print('-------------------------------------')
x2 = range(5, 10, 2)
for n in x2:
print(n)
if __name__ == '__main__':
main()
执行结果:
0
1
2
3
4
5
6
7
8
9
-------------------------------------
5
7
9
操作 | 结果说明 | 备注 |
x in s | x在s里存在则结果是True,否则是False | |
x not in s | x不在s里存在则结果是True,否则是False | |
s + t | 两个序列合并 | |
s * n 或 n * s | s是序列,n是整数 | |
s[i] | 取s中第i个元素,i从0开始 | |
s[i:j] | 取s中从i到j的元素,组成新的序列,即取子序列 | |
s[i:j:k] | 取s中从i到j的按k为步长的元素,组成新的序列 | |
len(s) | 序列长度 | |
minx(s) | 最小的序列元素 | |
max(s) | 最大的序列元素 | |
s.index[x, [, i[, j]]) | 查找元素x在序列s里的位置,如果i存在则从i下标处开始寻找,如果i和j都存在,则从i下标处开始,到j前面结束,注意不包括j位置。 | |
s.count(x) | 统计元素x在序列s中出现的次数 | |
上面操作是所有序列都具有的操作,也就是List, Tuple和Range类型对象都可以具有的操作,注意到没有,它们都是获取、查询类操作,并没有修改类的操作,因为也是不可修改的序列能够操作的,下面来一段代码验证:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 练习序列的通用操作
def main():
s = [1, 2, 3, 4]
if 1 in s:
print('1 is in s')
if 10 not in s:
print('10 is not in s')
t = [5, 6, 7]
s1 = s + t
print(s1)
s2 = s * 2
print(s2)
s3 = 2 * s
print(s3)
print(s[0], s[3])
print(s[0:3])
print(s[0:4:2])
print(len(s))
print(min(s))
print(max(s))
print(s.index(2))
print(s.index(2, 1))
print(s.index(3, 0, 3))
print(s1.count(1))
print(s2.count(3))
if __name__ == '__main__':
main()
可修改序列的特有操作,这些操作都是对序列本身内容进行了增删改的操作。
操作 | 结果说明 |
s[i] = x | 序列s第i个元素用x来取代,注意i是从0开始 |
s[i : j] = t | t是一个序列,用t的所有元素来取代s序列从i到j -1区间的元素,不包括j下标元素 |
del s[i : j] | 删除序列s中从i到 j - 1区间的元素,不包括j下标元素 |
s[i: j: k] = t | 用序列t所有元素,取代序列s中从i开始到j - 1, 两者元素数量要刚好一致,不然会出现异常 |
del s[i: j: k] | 删除序列s中从i到 j - 1区间的元素,但是以k为步长删除 |
s.append(x) | 在序列s尾部追加元素x |
s.clear() | 清除序列s中所有元素,s为空序列 |
s.copy() | 拷贝一份序列出来 |
s.extend(t)或 s += t | 把序列t追加到序列s后面 |
s *= n | 把序列s复制n份并追加起来 |
s.insert(i, x) | 在序列s的i下标处新增一个元素x, 也就是i开始的元素都后移动1位 |
s.pop([i]) | 把序列s的i下标处元素删除,如果i没提供,则默认最后一个元素被删除 |
s.remove(x) | 删除序列s中与x相等的第一个元素,注意不是所有 |
s.reverse() | 翻转 |
还是来一段测试验证代码吧:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 练习序列的通用操作
# 测试不可变操作
def test_immutable_operation():
s = [1, 2, 3, 4]
if 1 in s:
print('1 is in s')
if 10 not in s:
print('10 is not in s')
t = [5, 6, 7]
s1 = s + t
print(s1)
s2 = s * 2
print(s2)
s3 = 2 * s
print(s3)
print(s[0], s[3])
print(s[0:3])
print(s[0:4:2])
print(len(s))
print(min(s))
print(max(s))
print(s.index(2))
print(s.index(2, 1))
print(s.index(3, 0, 3))
print(s1.count(1))
print(s2.count(3))
# 测试可变操作
def test_mutable_operation():
s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
s[3] = 33
print(s)
t = (21, 22, 23)
s[1:2] = t
print(s)
del s[1:3]
print(s)
s[2:7:2] = [102, 104, 106]
print(s)
s.append(100)
print(s)
s.clear()
print(s)
s = [1, 2, 3, 4]
x = s.copy()
print(x)
t = [5, 6, 7, 8]
s += t
print(s)
s *= 2
print(s)
s.insert(2, 20)
print(s)
s.pop(10)
print(s)
s.pop()
print(s)
s.remove(7)
print(s)
s.reverse()
print(s)
def main():
# test_immutable_operation()
test_mutable_operation()
if __name__ == '__main__':
main()
上面的函数test_mutable_operation()就是测试可变序列的操作,大家可以去执行看看,想想是怎么回事。
关于Python序列讲的比其它数据类型多得多,因为数组是一个非常常用的数据结构,而序列List是一个可以看成可变长度的数组,在现实编程中使用特别多,了解越熟悉越好。
在序列List基础上,我们可以实现栈Stack,还可以实现队列Queue,多维数据也可以实现。
记住,Pascal编程语言之父的名言:数据结构 + 算法 = 程序。
记住,《Unix编程艺术》中Rob Pike提出的其中一个原则是:数据压倒一切;如果已经选择了正确的数据结构并把一切都组织的井井有条,那么正确的算法也就不言自明;编程的核心是数据结构,而不是算法。
Python编程语言容易学习,并不代表数据结构和算法容易学习,这里的容易学习是指Python帮我们封装实现了很多技术细节,不用向C和C++那么苦逼地自己去实现,但是我们一定要去理解背后的知识原理,不然我们面对简单的程序可能都处理不好。
陆游有诗句云:汝果欲学诗,工夫在诗外。真正要去编程,仅仅学习Python语言本身还是不行的。