注释
加入注释并不会对代码的运行产生影响,但加入注释可以使代码更加易懂易用。
1 2 3 4 5 6 7
|
""" 跨多行字符串会用三引号 (即三个单引号或三个双引号) 包裹,但也通常被用于注释 """
|
一切皆对象
在 Python 中,你无需事先声明变量名及其类型,直接赋值即可创建各种类型的变量:
1 2 3 4 5 6 7 8 9 10 11 12 13
| >>> x = -3 >>> x -3 >>> f = 3.1415926535897932384626; f 3.141592653589793 >>> s1 = "O" >>> s1 'O' >>> b = 'A' == 65 >>> b False >>> True + 1 == 2 and not False != 0 True
|
这不代表 Python 没有类型的概念,实际上解释器会根据赋值或运算自动推断变量类型,你可以使用内置函数 type() 查看这些变量的类型:
1 2 3 4 5 6 7 8
| >>> type(x) <class 'int'> >>> type(f) <class 'float'> >>> type(s1) <class 'str'> >>> type(b) <class 'bool'>
|
数字运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| >>> 5.0 * 6 30.0 >>> 15 / 3 5.0 >>> 5 / 100000 5e-05 >>> 5 // 3 1 >>> -5 // 3 -2 >>> 5 % 3 2 >>> -5 % 3 1 >>> x = abs(-1e4) >>> x += 1 >>> x 10001.0
|
除法运算(/)永远返回浮点类型(在 Python 2 中返回整数)。如果想要整数或向下取整的结果的话,可以使用整数除法(//)。同样的,也可以像 C++ 中一样,使用模(%)来计算余数,科学计数法的形式也相同。
特别地,Python 用 ** 即可进行幂运算,还通过内置的 pow(a, b, mod) 提供了 快速幂 的高效实现。
1 2 3 4 5 6 7 8
| >>> 3 ** 4 81 >>> 2 ** 512 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096 >>> pow(2, 512, int(1e4)) 4096 >>> 0.1 + 0.1 + 0.1 - 0.3 == 0. False
|
数据类型判断
对于一个变量,可以使用type(object)返回变量的类型,例如type(8)和type('a')的值分别为 <class 'int'>和<class 'str'>。
Python 中的输入输出主要通过内置函数 input() 和 print() 完成,print() 的用法十分符合直觉:
1 2 3 4 5 6 7 8 9
| >>> a = [1,2,3]; print(a[-1]) 3 >>> print(ans[0], ans[1]) 1 2 >>> print(a[0], a[1], end='') 1 2>>> >>> print(a[0], a[1], sep=', ') 1, 2 >>> print(str(a[0]) + ', ' + str(a[1]))
|
input() 函数的行为接近 C++ 中的 getline(),即将一整行作为字符串读入,且末尾没有换行符。
1 2 3
| >>> s = input('请输入一串数字: '); s 请输入一串数字: 1 2 3 4 5 6 '1 2 3 4 5 6'
|
字符串
Python 3 提供了强大的基于 Unicode 的字符串类型,使用起来和 C++ 中的 string 类似,一些概念如转义字符也都相通,除了加号拼接和索引访问,还额外支持数乘 * 重复字符串,和 in 操作符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| >>> s1 = "O" >>> s1 += 'I-Wiki' >>> 'OI' in s1 True >>> len(s1) 7 >>> s2 = """ 感谢你的阅读 ... 欢迎参与贡献! """ >>> s1 + s2 'OI-Wiki 感谢你的阅读\n欢迎参与贡献!' >>> print(s1 + s2) OI-Wiki 感谢你的阅读 欢迎参与贡献! >>> s2[2] * 2 + s2[3] + s2[-1] '谢谢你!' >>> s1[0] = 'o' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'str' object does not support item assignment
|
Python 支持多种复合数据类型,可将不同值组合在一起。最常用的 list,类型是用方括号标注、逗号分隔的一组值。例如,[1, 2, 3] 和 [‘a’,’b’,’c’] 都是列表。
除了索引,字符串还支持切片,它的设计非常精妙,格式为 s[左闭索引:右开索引:步长]:
1 2 3 4 5 6 7 8 9 10 11 12 13
| >>> s = 'OI-Wiki 感谢你的阅读\n欢迎参与贡献!' >>> s[:8] 'OI-Wiki ' >>> s[8:14] '感谢你的阅读' >>> s[-4:] '与贡献!' >>> s[8:14:2] '感你阅' >>> s[::-1] '!献贡与参迎欢\n读阅的你谢感 ikiW-IO' >>> s 'OI-Wiki 感谢你的阅读\n欢迎参与贡献!'
|
在最新的 Python 3 版本中,字符串是以 Unicode 编码的,也就是说,Python 的字符串支持多语言。1在 Python 中,可以对一个 Unicode 字符使用内置函数 ord() 将其转换为对应的 Unicode 编码,逆向的转换使用内置函数 chr()。C/C++ 中 char 类型也可以和 对应的 ASCII 码互转。
如果想把数字转换成对应的字符串,可以使用内置函数 str(),反之可以使用 int() 和 float(),你可以类比为 C/C++ 中的强制类型转换,但括号不是加在类型上而是作为函数的一部分括住参数。
Python 的字符串类型提供了许多强大的方法,包括计算某字符的索引与出现次数,转换大小写等等。
创建数组
列表(list)大概是 Python 中最常用也最强大的序列类型,列表中可以存放任意类型的元素,包括嵌套的列表,这符合数据结构中「广义表」的定义。请注意不要将其与 C++ STL 中的双向链表 list 混淆,故本文将使用「列表」而非 list 以免造成误解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| >>> [] [] >>> nums = [0, 1, 2, 3, 5, 8, 13]; nums [0, 1, 2, 3, 5, 8, 13] >>> nums[0] = 1; nums [1, 1, 2, 3, 5, 8, 13] >>> nums.append(nums[-2]+nums[-1]); nums [1, 1, 2, 3, 5, 8, 13, 21] >>> nums.pop() 21 >>> nums.insert(0, 1); nums [1, 1, 1, 2, 3, 5, 8, 13] >>> nums.remove(1); nums [1, 1, 2, 3, 5, 8, 13] >>> len(nums) 7 >>> nums.reverse(); nums [13, 8, 5, 3, 2, 1, 1] >>> sorted(nums) [1, 1, 2, 3, 5, 8, 13] >>> nums [13, 8, 5, 3, 2, 1, 1] >>> nums.sort(); nums [1, 1, 2, 3, 5, 8, 13] >>> nums.count(1) 2 >>> nums.index(1) 0 >>> nums.clear(); nums
|
以上示例展现了列表与 vector 的相似之处,vector 中常用的操作一般也都能在列表中找到对应方法,不过某些方法如 len(),sorted() 会以内置函数的面目出现,而 STL 算法中的函数如 find(),count(),max_element(),sort(),reverse() 在 Python 中又成了对象的方法,使用时需要注意区分。
将展示列表作为 Python 的基本序列类型的一些强大功能:
Python 支持多种复合数据类型,可将不同值组合在一起。最常用的 list,类型是用方括号标注、逗号分隔的一组值。例如,[1, 2, 3] 和 [‘a’,’b’,’c’] 都是列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| >>> lst = [1, '1'] + ["2", 3.0] >>> lst [1, '1', '2', 3.0] >>> 3 in lst True >>> [1, '1'] in lst False >>> lst[1:3] = [2, 3]; lst [1, 2, 3, 3.0] >>> lst[::-1] [3.0, 3, 2, 1] >>> lst *= 2; lst [1, 2, 3, 3.0, 1, 2, 3, 3.0] >>> del lst[4:]; lst [1, 2, 3, 3.0]
|
列表作为序列的一些常用操作,可以看出许多操作如切片是与字符串相通的,但字符串是「不可变序列」而列表是「可变序列」,故可以通过切片灵活地修改列表。在 C/C++ 中我们往往会通过循环处理字符数组,下面将展示如何使用 「列表推导式」 在字符串和列表之间转换:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| >>> >>> nums = list(range(65,70)) [65, 66, 67, 68, 69] >>> lst = [chr(x) for x in nums] >>> lst ['A', 'B', 'C', 'D', 'E'] >>> s = ''.join(lst); s 'ABCDE' >> list(s) ['A', 'B', 'C', 'D', 'E'] >>> >>> ''.join([chr(ord(ch) - 65 + 97) for ch in s if ch >= 'A' and ch <= 'Z']) 'abcde'
>>> vis = [[0] * 3] * 3 >>> vis [[0, 0, 0], [0, 0, 0], [0, 0, 0]] >>> vis[0][0] = 1; vis [[1, 0, 0], [1, 0, 0], [1, 0, 0]] >>> >>> a1 = [0, 0, 0]; a2 = a1; a3 = a1[:] >>> a1[0] = 1; a1 [1, 0, 0] >>> a2 [1, 0, 0] >>> a3 [0, 0, 0] >>> id(a1) == id(a2) and id(a1) != id(a3) True >>> vis2 = vis[:] >>> vis[0][1] = 2; vis >>> [[1, 2, 0], [1, 2, 0], [1, 2, 0]] >>> vis2 >>> [[1, 2, 0], [1, 2, 0], [1, 2, 0]] >>> id(vis) != id(vis2) True >>> >>> [id(vis[i]) == id(vis2[i]) for i in range(3)] [True, True, True] >>> >>> [id(x) for x in vis] [139760373248192, 139760373248192, 139760373248192]
|
Python 中赋值只传递了引用而非创建新值,可以创建不同类型的变量并赋给新变量,验证发现二者的标识值是相同的,只不过直到现在我们才介绍了列表这一种可变类型,而给数字、字符串这样的不可变类型赋新值时实际上创建了新的对象,故而前后两个变量互不干扰。但列表是可变类型,所以我们修改一个列表的元素时,另一个列表由于指向同一个对象所以也被修改了。创建二维数组也是类似的情况,示例中用乘法创建二维列表相当于把 [0]*3 这个一维列表重复了 3 遍,所以涉及其中一个列表的操作会同时影响其他两个列表。更不幸的是,在将二维列表赋给其他变量的时候,就算用切片来拷贝,也只是「浅拷贝」,其中的元素仍然指向相同的对象,解决这个问题需要使用标准库中的 deepcopy,或者尽量避免整个赋值二维列表。不过还好,创建二维列表时避免创建重复的列表还是比较简单,只需使用「列表推导式」:
1 2 3 4 5 6 7 8 9
| >>> vis1 = [[0] * 3 for _ in range(3)] >>> >>> vis1 [[0, 0, 0], [0, 0, 0], [0, 0, 0]] >>> [id(x) for x in vis1] [139685508981248, 139685508981568, 139685508981184] >>> vis1[0][0] = 1 [[1, 0, 0], [0, 0, 0], [0, 0, 0]] >>> a2[0][0] = 10
|
Python 是高度动态的解释型语言,因此其程序运行有大量的额外开销。尤其是 for 循环在 Python 中运行的奇慢无比。因此在使用 Python 时若想获得高性能,尽量使用列表推导式,或者 filter,map 等内置函数直接操作整个序列来避免循环,当然这还是要根据具体问题而定。
NumPy
利用 NumPy 建立多维数组并进行访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| >>> import numpy as np >>> np.empty(3) array([0.00000000e+000, 0.00000000e+000, 2.01191014e+180]) >>> np.zeros((3, 3)) array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) >>> a1 = np.zeros((3, 3), dtype=int) >>> a1[0][0] = 1 >>> a1[0, 0] = 1 >>> a1.shape (3, 3)
>>> a1[:2, :2] array([[1, 0], [0, 0]])
>>> a1[:, [0, 2]] array([[1, 0], [0, 0], [0, 0]]) >>> np.max(a1) 1 >>> a1.flatten() array([1, 0, 0, 0, 0, 0, 0, 0, 0])
>>> np.sort(a1, axis = 1) array([[0, 0, 1], [0, 0, 0], [0, 0, 0]]) >>> a1.sort(axis = 1)
|
array
array 是 Python 标准库提供的一种高效数值数组,可以紧凑地表示基本类型值的数组,但不支持数组嵌套