Python学习笔记(一)

第一章 基础知识

1. 基础

IDEA中安装Python插件,即可满足学习需要

IDE中要运行一个程序,必须写好这么一行

1
if __name__ == '__main__': 

意思是:当模块被直接运行时,以下代码块将被运行;当模块是被导入时,代码块不被运行。

输出:在 print() 内输入多个字符串,再用“,”连接,可以合在一起输出一个完整的字符串,遇到一个“,”就输出一个空格。
输出100+200的结果:

1
2
>>> print('100 + 200 =', 100 + 200)
100 + 200 = 300

要让print()函数输出后不换行:

1
2
3
4
>>> for i in range(10):
... print(i,end=' ')
...
0 1 2 3 4 5 6 7 8 9

输入:用 input() 让用户输入字符串,再存储到一个变量里。input() 可以让你显示一个字符串来提示用户,如:

1
name = input('please enter your name: ')

input()返回的都是str类型

1.1 变量

不需要声明类型,直接赋值就创建了一个变量

Python 动态类型语言——变量类型可以变化,在新声明之前,变量一直保持原来的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> type(var)  # 查看变量类型

>>> isinstance(54,str) # 查看是否为指定类型
False

>>> x=3
>>> print(x**2) # 乘方
9

>>> x=[1,2,3]
>>> x[1]=0 # 修改list(str和tuple不可修改)
>>> print(x)
[1, 0, 3]

>>> id(var) # 返回var的内存地址

相同的值在内存中只保留一份,多个变量可指向同一个地址

  • 变量名必须以字母或下划线开头
  • 名字中不能有空格和标点符号
  • 关键字也不行
1
2
3
>>> import keyword
>>> keyword.kwlist # 查看所有关键字
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
  • 变量名区分大小写

1.2 数字

不可变

标准库 import math

  • 十六进制必须以0x开头
  • 八进制必须以0o开头
  • 二进制必须以0b开头

虚数用j表示

1
2
3
4
5
>>> x=3+5j
>>> x.real # 查看实部
3.0
>>> x.imag # 查看虚部
5.0

Python中的布尔值本质就是0和1,因此可以和数字进行运算。bool值只有True和False两种。

1.3 字符串

不可变,可用一对单引号、双引号、三引号嵌套表示,支持用 + 合成

字符串引号前加 r 或 R 取消转义符

函 数 说 明
ord(str) 获取字符编码的整数表示
chr(str) 把编码转成字符
len(str) 计算 str 中包含的字符数
str.join(list) 用str来连接list中的各个成员
str.split([s]) s默认为空格,但不可以是’’,返回字符串列表list

join()函数用法如下:

1
2
3
>>> a = ['1','2','3','4']   # 序列中的元素也要是str类型
>>> "**".join(a) # 用**来链接序列的各个成员
'1**2**3**4'

1.4 运算符

符号示例 说明
x//y 求整数商
x**y
x or y 逻辑或(只有x为假才计算y)
x and y 逻辑与(只有x为真才计算y)
not x 逻辑非
x in y; x not in y 判断是否是成员
x is y; x is not y 测试内存地址(对象同一性)
1
2
3
4
5
6
7
8
9
10
>>> 'a'*6        # 字符重复
'aaaaaa'
>>> [1,2,3]*3 # list重复
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> (1,2,3)*2 # 元组重复
(1, 2, 3, 1, 2, 3)
>>> 3*[1,2,3] # 交换律
[1, 2, 3, 1, 2, 3, 1, 2, 3]

>>> x,y = y,x # 交换

1.5 常用内置函数

用 help(funname) 查看函数用法

函 数 功 能
abs(x) 绝对值
all(iterable) 若可迭代对象中所有bool(x)均为True,则函数返回True
any(iterable) 若可迭代对象中存在bool(x)为True,则函数返回True
bin(x) 将数字转为二进制串str
dir(x) 返回成员列表
list(x);set(x);tuple(x);dict(x) 把对象转成列表、集合、元组或字典
reverse(list or tuple) 逆序
sorted(x) 排序
int(x);float(x) 转类型

编码时优先考虑内置函数

del 命令删除变量的值,或序列的成员,或整个序列,但不可删除不可变序列的指定元素。

1.6 模块导入和使用

1
2
3
4
5
>>> import math as m  # 设置别名
>>> from math import sin # 导入明确对象
>>> sin(1) # 无序加模块名作为前缀
0.8414709848078965
>>> from random import * # 方便但不推荐

大项目中导入模块的顺序:导入标准库、导入第三方库、导入自己开发的本地库

2. 规范

  • 变量名尽量小写, 如有多个单词,用下划线隔开;类内部变量命名,用单下划线(_)开头(该变量可被继承访问);类内私有变量命名,用双下划线(__)开头(该变量不可被继承访问) school_name = ‘ujs’
  • 常量采用全大写,如有多个单词,使用下划线隔开 MAX_CONNECTION = 1000
  • 函数名一律小写,如有多个单词,用下划线隔开 def run_with_env():
  • 类内部函数命名,用单下划线(_)开头(该函数可被继承访问)
  • 类内私有函数命名,用双下划线(__)开头(该函数不可被继承访问)
  • 类名使用驼峰(CamelCase)命名风格,首字母大写,私有类可用一个下划线开头 class AnimalFarm(Farm):
  • 函数之间空两行,类成员函数之间空一行
  • 每个import尽量只导入一个模块

3. 包的使用

每个目录中都必须包含一个 __init__.py 文件(可以是空),以表示该目录是一个包

按照包的结构用 ”.“ 分隔import,类似于Java

第二章 序列

无序序列:字典(3.6开始字典也是有序的了)、集合

列表、元组、字符串可双向索引,亦可用负数索引,最后一个元素是-1,倒数第二个是-2……

1. 列表

一个列表中的元素类型可以不同

方 法 说 明
list.append(x) 末尾追加
list.extend(L) 末尾加上L的所有元素
list.insert(index,x) 指定位置添加(index前面)
list.remove(x) 删除首次出现的x,若不存在则抛异常
list.pop([index]) 删除并返回指定位置的元素,默认是最后一个元素
list.clear() 清空列表成员,但保留列表对象
list.index(x) 返回首次出现x的位置,如果没有就抛异常
list.count(x) 统计x出现的次数
list.reverse() 原地翻转
list.sort() 排序(Unicode),会改变原有list
list.copy() 浅拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> l = list(range(1,10,2))   # range三个参数注意区别,第二个参数取不到
>>> l
[1, 3, 5, 7, 9]

# append()、extend()、+= 的辨析
>>> arr = [1,2,3]
>>> arr.append(4) # 末尾添加一个元素4
>>> arr
[1, 2, 3, 4]
>>> arr.append([5,6,7]) # 末尾添加一个元素[5,6,7]
>>> arr
[1, 2, 3, 4, [5, 6, 7]]
>>> arr.extend([6,0,6]) # 末尾扩展加上三个元素
>>> arr
[1, 2, 3, 4, [5, 6, 7], 6, 0, 6]
>>> arr.extend({8,8,8}) # extend()可接收iterable的参数
>>> arr
[1, 2, 3, 4, [5, 6, 7], 6, 0, 6, 8]
>>> arr+=('a','b') # extend() 与 += 效果完全一样,推荐用+=
>>> arr
[1, 2, 3, 4, [5, 6, 7], 6, 0, 6, 8, 'a', 'b']

注意:extend() 与 += 效果完全一样,而extend()涉及函数调用,效率差一点,因此推荐用+=

列表中修改序列某成员,不改变改列表对象本身的地址

用乘法扩展(重复)原序列,该操作实际创建了一个新序列。且这些重复是已有对象的引用,如下所示:

1
2
3
4
5
6
>>> x = [[1,2,3]]*3
>>> x
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>> x[0][0]=10
>>> x
[[10, 2, 3], [10, 2, 3], [10, 2, 3]] # 重复对象也发生了改变

查看某个元素是否在序列中,可用 in / not in 关键字

切片 用两个冒号分隔的三个数字完成,数字分别表示开始位置(默认0)、结束(但不包含)位置(默认为序列长度)、步长(默认1)。切片不会因为越界而抛出异常

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
# 逆序
>>> x=[1,2,3]
>>> x [::-1]
[3, 2, 1]

# 末尾添加
>>> x[len(x):] = [4]
>>> x
[1, 2, 3, 4]

# 删除部分
>>> x = [1,2,3,4]
>>> x[:2]=[]
>>> x
[3, 4]

# 修改
>>> x[:2]=[1,2]
>>> x
[1, 2]

>>> x= list(range(10))
>>> x[::2] = [0] * (len(x)//2) # 每隔一个变为0
>>> x
[0, 1, 0, 3, 0, 5, 0, 7, 0, 9]

Python中 == 比较两者的值, is 比较两者的内存地址

1
2
3
4
5
6
7
8
9
>>> list1 = [1]
>>> list2 = list1[::] # 浅拷贝,修改不互相影响
>>> list1 == list2
True
>>> list1 is list2
False
>>> list1[0] = 2
>>> list1 [2]
>>> list2 [1]

常用内置函数

  • sort() 函数改变原有对象,sort(reverse = True) 降序排序
  • sorted() 函数返回新对象, sorted(list, reverse = True) 降序,注意它的返回值永远是list类型,可以对tuple以及str等进行排序
1
2
3
4
5
>>> s = 'ueigb'
>>> sorted(s)
['b', 'e', 'g', 'i', 'u'] # 返回排序的数组
>>> ''.join(_)
'begiu' # 再加一步实现类似字符串排序的效果
  • reverse() 和 reversed() 同理
  • max(dict)、min(dict) 对字典进行比较时,使用的是key,返回的也是key;若要比较value,就用dict.values()
  • zip(list1, list2 …) 将多个列表或元组合为一个元组,返回一个zip对象,示例:
1
2
3
4
5
6
7
8
9
10
11
12
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> c = [7,8,9]
>>> x = zip(a,b,c)
>>> x
<zip object at 0x00000197CD943640>
>>> list(x) # 要转成列表等才可打印
[(1, 4, 7), (2, 5, 8), (3, 6, 9)] # 每组取一个合成
>>> c = [7,8]
>>> x = zip(a,b,c)
>>> list(x)
[(1, 4, 7), (2, 5, 8)] # c组少一个,最终合成也少一组
  • enumerate,枚举列表、元组、字符串、字典等可迭代对象,返回多个(下标, 成员)二元组。

  • strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。

    注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。

列表推导式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>> [x * x for x in range(1, 11) if x % 2 == 0]  # 生成偶数的平方
[4, 16, 36, 64, 100]

>>> [m + n for m in 'ABC' for n in 'XYZ'] # 两层循环
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

>>> vec = [[1,2,3],[4,5,6],[7,8,9]]
>>> [num for elem in vec for num in elem] # 嵌套列表的p
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> from math import sqrt # 输出100以内所有的素数
>>> [p for p in range(2,100) if 0 not in [p%d for d in range(2, int(sqrt(p))+1)]]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

# 矩阵转置
>>> matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
>>> reverse_matrix = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
>>> reverse_matrix
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

# 生成新的3 x 4二维矩阵
>>> [[0]*4 for _ in range(3)]
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

2. 元组

若要创建只包含一个元素的的元组,要在元素后另加一个逗号,否则会被当成数学运算中的小括号,例如:

1
2
3
4
5
6
>>> x = ('a')
>>> type(x)
<class 'str'>
>>> y = ('a',)
>>> type(y)
<class 'tuple'>

元组访问处理的速度比列表快,若仅用于遍历访问等,则优先使用元组

2.1 序列解包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> x,y,x=1,2,3    # 同时赋值

# 函数传参时序列解包
>>> def demo(a,b,c):
... print(a + b + c)
>>> s = [1,2,3]
>>> demo(* s)
6

>>> s = {'a':1, 'b':2, 'c':3}
>>> demo(* s) # 默认操作key
abc
>>> demo(** s) # 操作value值
6

2.2 生成器推导式

把列表推导式的[]换成(),结果输出一个生成器类型的对象,用 __next__() 方法进行遍历。当所有元素遍历结束后,要重新建立生成器对象才能再次遍历。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
>>> x = ((i+2)**2 for i in range(10))
>>> x
<generator object <genexpr> at 0x0000025476CCCDD0> # 生成器类型的对象
>>> list(x)
[4, 9, 16, 25, 36, 49, 64, 81, 100, 121]
>>> list(x)
[] # 无法再次遍历
>>> x = ((i+2)**2 for i in range(10)) # 重新建立对象
>>> x.__next__() # 逐步遍历
4
>>> x.__next__()
9

3. 字典

字典的键是不可变类型,如整数、元组、字符串等。一个对象能不能作为字典的key,就取决于其有没有__hash__方法。所以所有python自带类型中,除了list、dict、set和内部至少带有上述三种类型之一的tuple之外,其余的对象都能当key。

对字典操作默认是其key,若要操作value用 .values(),若要操作键值对用 .items()

内置函数 locals() 查看当前作用域内变量和值的字典,globals() 查看全局变量和值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 用zip()和dict()快速创建字典
>>> a = list('abc')
>>> b = [1,2,3]
>>> d = dict(zip(a,b))
>>> d
{'a': 1, 'b': 2, 'c': 3}

>>> dict(name='Harry',age=36,gender='Male')
{'name': 'Harry', 'age': 36, 'gender': 'Male'}

>>> dict.fromkeys(['name','age','gender']) # 创建只有key没有value的字典
{'name': None, 'age': None, 'gender': None}

>>> x = dict(name='Harry',age=36,gender='Male')
>>> x['age'] # 直接访问,但不推荐
36
>>> x.get('name') # 更推荐使用get()访问
'Harry'
>>> x.get('nation') # 此时无结果
>>> x.get('nation','China') # 无结果时可以指定返回值
'China'

当以指定“键”为下标为字典元素赋值时,若该“键”存在,则表示修改该“键”的值;若不存在,则表示添加一个新的“键—值对”,也就是添加一个新元素。

使用字典对象的update() 方法将另一个字典的“键值对”一次性全部添加到当前字典对象,如果两个字典中存在相同的“键”,则以另一个字典中的“值”为准对当前字典进行更新。

del() 删除指定key,pop() 删除并返回指定key,popitem() 默认删除最后一个键值对

4. 集合

集合中的元素必须是不可变类型

set() 函数在创建新集合时也会进行去重,算法中可以利用这点

add() 添加一个元素,pop() 弹出并返回一个元素,remove() 删除指定元素

  • | 或者 union() 表示并集
  • & 或者 intersection() 表示交集
  • - 或者 a.difference(b) 表示差集,从a中去掉b中也有的元素
  • ^ 或者 symmetric_difference() 表示对称差
  • <、> 的比较是看是否全部包含
  • issubset() 是否为子集

序列越长,使用集合的效率越高

5. 复杂数据结构

5.1 堆

1
2
3
4
5
6
import heapq
heaqp.heappush() # 入堆(默认小根堆)
heaqp.heappop() # 弹出堆顶,堆自动调整
heaqp.heapify(list) # 调整成堆
heaqp.nlargest(3,myheap) # 最大的三个数
heaqp.nsmallest(3,myheap) # 最小的三个数

5.2 队列

1
2
3
4
5
import queue
q = queue.Queue() # 初始化
q.put(elem) # 入队
q.queue # 查看队列
q.get() # 出队

5.3 栈、链表

Python自带的list类型可以基本模拟栈和链表。更好的是自己实现模拟。