py代码规范:
1.空格表示缩进,不可随意加,一个制表符表示一个缩进层次
2.每个语句需从新一行的第一列开始
3.区分大小写
注释:
行注释:每行前加#,如: #我是注释
段注释:两边三个单引号包起来,如: '''
我是注释1
我是注释2
'''
绘图
例:
import turtle
turtle.showturtle()
turtle.forward(100)
turtle.color("red")
turtle.left(90)
turtle.forward(100)
turtle.goto(0, 0)
turtle.write("jzx")
turtle.penup()
turtle.goto(0, 100)
turtle.pendown()
turtle.circle(100)
模块导入
>>> from math import sqrt
>>> sqrt(9)
3.0
也可以使用变量来引用函数,如
>>> foo = math.sqrt
>>> foo(4)
2.0
>>> import cmath # 复数,虚数被视为实部为零的复数
>>> cmath.sqrt(-1)
1j
行连接符 ,将多行连接成一行
如:
>>> 1 + 2 +
4 + 5
12
对象
由:标识、类型、值组成
id(obj) 返回对象id
type(obj) 返回对象类型
print(obj) 打印对象的值
例:
>>> a = 3
>>> a
3
>>> id(a)
140706621842128
>>> type(a)
<class 'int'>
>>> print(a)
3
变量实则为对象的引用
Python是动态类型语言,强类型语言
若使用Python自带的IDLE,按F1可打开帮助文档
标识符命名规范
模块和包名 全小写,多个单词之间用下划线
函数名 全小写,多个单词之间用下划线
类名 首字母大写,驼峰原则,多个单词之间用下划线
常量名 全大写,多个单词之间用下划线
变量删除
del 变量名
系列解包赋值
a, b, c = 4, 5, 6
变量值互换
a, b = b, a
常量
MAX = 100 #实际上可以修改,但Python不支持常量,只能逻辑上不做修改
运算符
/ 浮点数除法
// 整数除法
** 幂
| 按位或
^ 按位异或
& 按位与
<< >> 位移
注:不支持自增、自减!
使用divmod()函数同时获得商和余数
>>>div(13,3)
(4,1)
整数
二进制 0b或0B开头
八进制 0o或0O开头
十六进制 0x或0X开头
使用int()、float()实现类型转换
int(9.9) 为9
float(9) 为9.0
浮点数
3.14科学计数法表示为314e-2
四舍五入
round(3.14) 为3
时间表示
1970年1月1日称为Unix时间点
time.time()返回当前到Unix时间点所经过的时间(毫秒)
比较运算符
== 对象的值是否相等
!=
>
<
>=
<=
逻辑运算符
or 如 x or y
and 如 x and y
not 如 not x
同一运算符
is 判断两个标识符是否引用了同一对象
is not
整数缓存问题
对较小的整数进行缓存,命令行模式下为(-5~256),文件模式下为(任意整数,py3.7)
>>> a = 1000
>>> b = 1000 # 命令行模式下,超过256不缓存
>>> a == b
True
>>> a is b
False
>>> c = 10 # 较小整数
>>> d = 10
>>> c is d
True
字符串
单引号或双引号
ord() 把字符转换为对应Unicode码,如ord('A')为65
chr() 把十进制数字转换成对应字符,如 chr(39640)为'高'
len() 计算字符串长度
+ 字符串拼接,返回新的字符串
* 字符串复制,如a = 'xiao'*3
序列与数x相乘,重复创建x次
例:
>>> 'jzx'*3
'jzxjzxjzx'
print("aa", end=" ") 打印以制表符结尾
input() 从控制台读取键盘输入的内容
str() 将数字转换为字符串
[] 提取字符串中的字符,如 s = "abcd" 则s[0]为a,s[-1]为d
replace() 替换字符,如
例:
>>> s = "abc"
>>> s.repalce('a','b') # 返回把a替换成b后的字符
"bbc"
>>> s
"abc"
>>> s = s.replace('a','b')
>>> s
"bbc"
slice() 截取字符串
例:>>> a = "abcdefgh"
>>> a[1:5] # 截取索引1到4的字符
'bcde'
>>> a[1:5:2] # 步长为2
'bd'
>>> a[:] # 截取所有
'abcdefgh'
>>> a[2:] # 从索引2开始截取到尾部
'cdefgh'
>>> a[:3] # 从开头截取到索引为2的字符
'abc'
>>> a[-3:] # 截取倒数三个
'fgh'
>>> a[::-1] # 范围从头到尾,步长为负数,从右向左截取
'hgfedcba'
注:步长为负数时,第一个索引必须比第二个索引大
split() 用指定字符将字符串分割,若不指定,默认为空格符
例:
>>> a="a b c"
>>> a.split() # 默认以空格分隔
['a', 'b', 'c']
>>> a.split('b')
['a ', ' c']
join() 用指定字符将字符串连接起来
例:
>>> a = ["a",'b','c']
>>> '*'.join(a) # 用*将a中字符连接起来
'a*b*c'
小结
不建议使用+连接,效率不高
例:
import time
time01 = time.time()
a = ""
for i in range(100000):
a += "jzx"
time02 = time.time()
print(str(time02 - time01))
time03 = time.time()
li = [] # 空列表
for i in range(100000):
li.append("jzx")
a = "".join(li)
time04 = time.time()
print(str(time04 - time03))
结果:
0.02698349952697754
0.013010978698730469
字符串驻留
对符合标识符规则的字符串采用驻留机制
>>> a = "abc_"
>>> b = "abc_"
>>> a is b
True
>>> c = "ab#" #含有不符合标识符的字符
>>> d = "ab#"
>>> c is d
False
字符串比较和同一性
==、!= 比较是否含有相同的字符
is、not is 比较是否是同一对象
成员操作符
in、not in 判断某个字符是否在字符串中
常用查找方法
例:
>>> s = "abcdcef"
>>> len(s)
7
>>> s.startswith('a')
True
>>> s.endswith('f')
True
>>> s.find('c') # 查找第一次出现的位置
2
>>> s.rfind('c') # 查找最后一次出现的位置
4
strip() 去除字符串首尾的指定信息,默认去除空格符
例:
>>> a = " jzx "
>>> a.strip()
'jzx'
>>> a = "#jzx#"
>>> a.strip('#')
'jzx'
>>> a.lstrip("#")
'jzx#'
>>> a.rstrip('#')
'#jzx'
find
在字符串中查找子串,找到则返回第一个字符的索引,否则返回-1
>>> title = "jzx is very good"
>>> title.find('jzx')
0
大小写转换
例:
>>> a = "my book is GRE"
>>> a.capitalize()
'My book is gre'
>>> a.title()
'My Book Is Gre'
>>> a.upper()
'MY BOOK IS GRE'
>>> a.lower()
'my book is gre'
>>> a.swapcase()
'MY BOOK IS gre'
格式排版
例:
>>> a = "jzx"
>>> a.center(10,'*')
'***jzx****'
>>> a.center(10) # 未指定则默认为空格
' jzx '
>>> a.ljust(10,'*')
'jzx*******'
>>> a.rjust(10,'*')
'*******jzx'
如函数调用返回一个序列,可直接进行索引操作
例:
>>> fourth = input('输入年份:')[3] # 直接获取输入字符中的第4个字符存入a
输入年份:2019
>>> fourth
'9'
字符串其他方法
isalnum 是否为字母或数字
isalpha 是否只有字母(含汉字(Unicode编码))
isdigit 是否只有数字
isspace 是否为空格符
isupper 是否为大写
islower 是否为小写
format() 格式化
例:
>>> a = "姓名:{0},年龄:{1}"
>>> a.format("小明",18)
'姓名:小明,年龄:18'
>>> b = "姓名:{name}.年龄{age}"
>>> b.format(age = 20, name = "小红")
'姓名:小红.年龄20'
>>> a=2
>>> print("a=%i" %a)
a=2
>>> print("a=%f" %a)
a=2.000000
>>> print("a=%.2f" %a)
a=2.00
>>> b = "jzx"
>>> print("b=%s" %b)
b=jzx
>>> name = ["jzx", "jxx"]
>>>"My name is {myname[0]}".format(myname = name)
'My name is jzx'
>>> import math
>>> tmpl = "The mod.__name__ module defines the value {mod.pi} for π"
>>>tmpl.format(mod = math)
'The math module defines the value 3.141592653589793 for π'
>>> print("{pi!s} {pi!r} {pi!a}".format(pi = "π") # str repr ascii方式转换
π 'π' 'u03c0'
>>> "{num:4}".format(num = 22)
' 22'
>>> "The number is {num}".format(num = 22)
'The number is 22'
>>> "The number is {num:f}".format(num = 22) # 类型说明符
'The number is 22.0'
>>> "The number is {num:b}".format(num = 22)
'The number is 10110'
…………………………
>>> '{:,}'.format(1000) # 千位分隔符
'1,000'
当变量与替换字段同名时,在字符串前面加上f
>>> from math import e # 引入自然常数
>>> f"Euler's constant is roughly {e}" # 自然常数与普通变量e一样
"Euler's constant is roughly 2.718281228459045"
或
>>> "Euler's constant is roughly {e}".format(e = e)
"Euler's constant is roughly 2.718281228459045"
填充与对齐
例:
>>> "{:*>8}".format("245") # 居右,共8个占位,*号填充
'*****245'
>>> "{:*^8}".format("245")
'**245***'
>>> "{:*<8}".format("245")
'245*****'
数字格式化
数字 格式 输出 描述
3.1415926 {:.2f} 3.14 保留小数点后两位
3.1425926 {:+.2f} 3.14 带符号保留小数点后两位
2.71828 {:.0f} 3 不带小数
5 {:0>2d} 5 数字补零(填充左边,宽度为2)
5 {:x<4d} 5xxx 数字补x(填充右边,宽度为4)
10 {:x<4d} 10xxx 数字补x(填充右边,宽度为4)
1000000 {:,} 1,000,000 以逗号分隔
0.25 {:.2%} 25.00% 保留小数两位的百分比格式
1000000000 {:.2e} 1.00E+09 保留小数两位的指数计法
13 {:10d} 13 右对齐(默认,宽度10)
13 {:<10d} 13 左对齐,宽度10
13 {:^10d} 13 居中对齐。宽度10
可变字符串
Python中字符串是不可变对象,不支持原地修改。需创建新的字符串对象修改
例:
>>> import io
>>> s = "hello,jzx"
>>> sio = io.StringIO(s)
>>> sio
<_io.StringIO object at 0x000001515F8A6798>
>>> sio.getvalue()
'hello,jzx'
>>> sio.seek(7)
7
>>> sio.write('x') # 将第7个字符改为x
1
>>> sio.getvalue()
'hello,jxx'
容器一般是可包含其他对象的对象,主要是序列(列表和元组)、映射(字典)、集合
序列
序列是一块用来存放多个的连续内存空间
例如序列[10,20,30,40]
Python3中一切皆为对象,a = [10,20,30,40]存储方式如下
常用的序列结构有:字符串、列表、元组、字典、集合
列表
可以存放任意的数据类型,长度可变
例:a=[10,"abc",True]
方法 描述
list.append(x) 将元素x增加到list尾部
list.extend(aList) 将aList列表增加到list列表
list.insert(index,x)在指定位置插入元素
list.remove(x) 删除首次出现的指定元素
list.pop([index]) 删除并返回指定位置的元素,默认最后一个元素
list.clear() 删除列表所有元素
list.index(x[,start[,end]]) 返回指定范围中第一个x的索引位置,不存在则抛出异常
list.count(x) 返回指定元素x在列表出现的次数
list.reverse() 所有元素原地反转
list.sort() 所有元素原地稳定排序,不返回,内置函数sorted返回
list.copy() 返回列表元素的浅拷贝
列表的创建
>>> a = [] #创建一个空列表
>>> a = list() #创建一个空列表
>>> a = list(range(10)) # 0~9
>>> a
[0,1,2,3,4,5,6,7,8,9]
>>> a = list("xiaoming,xiaogang") # 每个字符为一个元素
>>> a
['x', 'i', 'a', 'o', 'm', 'i', 'n', 'g', ',', 'x', 'i', 'a', 'o', 'g', 'a', 'n', 'g']
>>> sequence = [None]*3 # 初始化3个元素为none的列表
>>> sequence
[None,None,None]
range()函数
range([start,] end[,step])
start不写默认为0
step默认为1
返回的是range对象
例:
>>> a = [x*2 for x in range(10)]
>>> a
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
del删除列表元素
例:
>>> a = [100,200,300]
>>> del a[1]
>>> a
[100, 300]
pop() 方法
例:
>>> a = [100,200,300,400]
>>> b = a.pop(1) # 将索引1处的元素弹出
>>> b
200
>>> a
[100, 300, 400]
列表的切片操作
与字符串的类似
例:
>>> a = [100,200,300,400, 500, 600, 700]
>>> a
[100, 200, 300, 400, 500, 600, 700]
>>> a[1:5:1] #从索引1到4步长为1
[200, 300, 400, 500]
给切片赋值
>>> name = list('Perl')
>>> name
['P', 'e', 'r' ,'l']
>>> name[2:] = list('ar') # 修改索引2到最后的字符为 'ar'
>>> name
['P', 'e', 'a', 'e']
>>> name = list('Perl')
>>> name[1:] = list('ython') # 同时修改了长度
>>> name
['P', 'y', 't', 'h', 'o', 'n']
>>> numbers = [1, 5]
>>> numbers[1:1] = [2, 3, 4] # 插入新元素(相当于替换空切片)
>>> numbers
[1, 2, 3, 4, 5]
>>> numbers[1:4] = [] # 空切片替换实现删除
>>> numbers
[1, 5]
列表的遍历
例:
>>> for x in a:
... print(x)
...
100
200
300
400
500
600
700
列表的复制
例:
>>> list1 = [1, 2, 3, 4]
>>> list2 = list1
>>> list2 # list1与list2都指向同一列表对象
[1, 2, 3, 4]
列表的排序
例:
>>> a = [20, 10, 5, 40, 7]
>>> id(a)
2244260923272
>>> a.sort() # 不返回
>>> a
[5, 7, 10, 20, 40]
>>> id(a)
2244260923272
>>> a.sort(reverse = True) # 指定排序方式,不返回
>>> a
[40, 20, 10, 7, 5]
>>> id(a)
2244260923272
>>> import random
>>> random.shuffle(a) # 随机打乱
>>> a
[10, 7, 20, 40, 5]
高级排序
>>> x = ['abcd', 'ab', 'abc']
>>> x.sort(key = len) # 设置按照长度大小排序
>>> x
['ab', 'abc', 'abcd']
建新列表排序
例:
>>> a = [1, 5, 2, 6, 3]
>>> id(a)
1727490895944
>>> a = sorted(a) # 返回排完的列表
>>> a
[1, 2, 3, 5, 6]
>>> id(a)
1727494012552
reversed()返回迭代器
内置函数reversed()
例:
>>> a = [2, 1, 5, 3, 6]
>>> b = reversed(a)
>>> b # b是迭代器
<list_reverseiterator object at 0x0000019236A7A048>
>>> list(b)
[6, 3, 5, 1, 2]
二维列表
例:
>>> a = [
["xiaoming", 20],
["xiaogang", 22]
]
>>> a
[['xiaoming', 20], ['xiaogang', 22]]
>>> for m in range(2):
for n in range(2):
print(a[m][n], end=" ")
print() #打印一行之后换行
xiaoming 20
xiaogang 22
元组
元组属于不可变序列,不能修改元素
元组的创建
使用 () 创建,或省略
例:
>>> a = (10, 20, 30) # 方式一
(10, 20, 30)
>>> a = 10,20,30 # 方式二
(10, 20, 30)
>>> a = (1,) # 若只有一个元素,后面必须加 ,
(1,)
>>> a = 1,
(1,)
>>> () # 空元组
()
>>> 3 * (10,)
(10, 10, 10)
通过tuple()创建
tuple将序列转换成元组
例:
>>> tuple([1, 2, 3])
(1, 2, 3)
>>> tuple('abc')
('a', 'b', 'c')
>>> tuple((1, 2, 3))
(1, 2, 3)
b = tuple() # 创建空的元组对象
b = tuple("abc")
b = tuple(range(3))
b = tuple([2,3,4])
del b #元组对象的删除
tuple()可以接收列表、字符串、其他序列类型、迭代器等生成元组
list() 可以接收元组、字符串、其他序列类型、迭代器等生成列表
元组切片
与字符串的类似
例:
>>> x = 1, 2, 3
>>> x[1]
2
>>> x[0:2]
(1, 2)
元组排序
例:
>>> a = (20, 10, 40, 30)
>>> sorted(a) # 返回列表
[10, 20, 30, 40]
zip()方法
同索引位元素生成新元组
例:
>>> a = (20, 10, 40, 30)
>>> b = (11, 22, 33)
>>> c = zip(a,b)
>>> c
<zip object at 0x000002477AD2F8C8>
>>> list(c)
[(20, 11), (10, 22), (40, 33)]
生成器推导式创建元组
>>> s = (x * 2 for x in range(5))
>>> s
<generator object <genexpr> at 0x000002477ACDF570>
>>> tuple(s)
(0, 2, 4, 6, 8)
>>> tuple(s) # 只能用一次,第二次失效,因为指针不再指向开头
()
>>> s = (x * 2 for x in range(5))
>>> s.__next__() # 双下划线
0
>>> s.__next__()
2
>>> s.__next__()
4
>>> s.__next__()
6
>>> s.__next__()
8
其他方法与列表类似
小结
访问速度比列表快
与整数和字符串一样,元组可以作为字典的键,而列表则不可以
字典
字典是“键值对”的无序列表,每个元素都是键值对,包含“键对象”与“值对象”
通过“键对象”快速获取、删除、修改“值对象”
键是任意的、不可重复的不可变数据,包括:整数、浮点数、字符串、元组
字典的创建
1.通过 {}、dict()来创建
例:
>>> a = {'name': 'xiaoming', 'age':18}
>>> a = dict(name = 'xiaoming', age=18)
>>> a = dict([("name", "xiaoming"), ("age", 18)])
2.通过zip()创建
例:
>>> k = ['name', 'age']
>>> v = ['xiaoming', 18]
>>> d = dict(zip(k, v))
>>> d
{'name': 'xiaoming', 'age': 18}
3.通过fromkeys创建值为空的字典
>>> a = dict.fromkeys(['name', 'age'])
>>> a
{'name': None, 'age': None}
字典元素的访问
1.通过“键”获得“值”
例:
>>> a = {'name': 'xiaoming', 'age':18}
>>> a['name']
'xiaoming'
2.通过get()方法获得“值”
>>> a.get('age') # get()方法,推荐
18
>>> a.get('sex') #不存在返回None
>>> print(a.get('sex'))
None
3.列出所有键值对
例:
>>> a.items()
dict_items([('name', 'xiaoming'), ('age', 18)])
4.列出所有的键、列出所有的值
例:
>>> a.keys()
dict_keys(['name', 'age'])
>>> a.values()
dict_values(['xiaoming', 18])
5. len()返回键值对个数
例:
>>> len(a)
2
6. in检测“键”是否在字典中
例:
>>> "name" in a
True
字典元素的修改
1.新增键值对(若已存在则覆盖旧值)
例:
>>> a = {'name':'xiaoming','age':18}
>>> a['address'] = 'beijing'
>>> a
{'name': 'xiaoming', 'age': 18, 'address': 'beijing'}
2.使用update()将新字典的所有键值对加到旧字典对象(key重复则覆盖)
例:
>>> a = {'name':'xiaoming'}
>>> b = {'id':1}
>>> a.update(b)
>>> a
{'name': 'xiaoming', 'id': 1}
3.del()删除元素、clear()清除所有键值对、pop()删除指定键,并返回值对象
例:
>>> a = {'name':'xiaoming'}
>>> b = {'id':1}
>>> a.update(b)
>>> a
{'name': 'xiaoming', 'id': 1}
>>> del(a['name'])
{'id': 1}
>>> print(a.pop('id'))
1
4.popitem()随机弹出一个字典项并返回(字典无序,没有“最后一个”概念)
例:
>>> a = {'name': 'xiaoming', 'age': 18, 'address': 'beijing'}
>>> a.popitem()
('address', 'beijing')
>>> a.popitem()
('age', 18)
>>> a.popitem()
('name', 'xiaoming')
5.format_map()
例:
>>> phonebook = {'jzx': '1885257'}
>>> "jzx's phone number is {jzx}".format_map(phonebook)
"jzx's phone number is 1885257"
6.setdefault()
例:
>>> d = {}
>>> d.setdefault('name', 'N/A') # 指定键不存在时设置成对应值
'N/A'
>>> d
{'name': 'N/A'}
>>> d['name'] = 'jzx'
>>> d.setdefault('name', 'N/A') # 指定键存在时返回对应值
'jzx'
>>> d
{'name': 'jzx'}
7.values()
例:
>>> d = {}
>>> d[1] = 1 #数字作为键
>>> d[2] = 2
>>>d.values() # 返回的值可以包含重复的值
dict_values([1, 2])
字典底层原理
字典对象的核心是散列表。散列表是一个稀疏数组,每个单元叫做bucket,bucket中含键对象的引用、值对象的引用,
所有的bucket结构和大小一致
key1 value1
key2 value2
若将键值对'"name"="jzx"存放到字典中,首先计算"name"的散列值,Python通过hash()计算,例:
>>> a={}
>>> a['name']="jzx"
>>> bin(hash("name"))
'0b111100101001111001100000110000110101110101010011010000101100000'
然后根据散列值进行分配位置存放
序列解包
用于元组、列表、字典
例:
>>> x, y, z = (10, 20,30) #或(x, y, z) = (10, 20, 30)或[x, y, z] = [10, 20, 30]
>>> x
10
>>> y
20
>>> z
30
>>> a = {'name': 'xiaoming', 'age': 18, 'address': 'beijing'}
>>> x, y, z = a
>>> a
{'name': 'xiaoming', 'age': 18, 'address': 'beijing'}
>>> x # 只返回键值
'name'
>>> y
'age'
>>> z
'address'
>>> x1, y1, z1 = a.items() # 键值对
>>> x1
('name', 'xiaoming')
>>> y1
('age', 18)
>>> z1
('address', 'beijing')
>>> x2, y2, z3 = a.values() # 值对象
>>> x2
'xiaoming'
>>> y2
18
>>> z2
'beijing'
assert
assert语句充当检查点
例:
>>> age = -1
>>> assert 0 < age <10, 'The age must be realistic'
Traceback (most recent call last):
File "stdin", line 1,in ?
AssertionError:The age must be realistic
pass语句
表示什么都不做
集合
集合是无序可变,元素不能重复
1.使用 {} 创建集合
例:
>>> a = {1, 30, 22}
>>> a.add(30) # 添加重复元素
>>> a
{1, 30, 22}
>>>b = set() # 创建空集合
2.使用set,将元组、列表等可迭代对象转换成集合
例:
>>> a = [1, 2, 2, 3]
>>> b = set(a)
>>> b
{1, 2, 3}
3.remove()删除指定元素;clear()清空集合
例:
>>> a = {10, 20, 30, 40, 50}
>>> a.remove(10)
>>> a
{40, 50, 20, 30}
集合
例:
>>> a = {1, 2, 'jzx'}
>>> b = {3, 4, 'jzx'}
>>> a | b # 并集
{1, 2, 3, 4, 'jzx'}
>>> a.union(b) # 并集
{1, 2, 3, 4, 'jzx'}
>>> a & b # 交集
{'jzx'}
>>> a.intersection(b) # 交集
{'jzx'}
>>> a - b # 差集
{1, 2}
>>> a.difference(b) # 差集
{1, 2}
>>> a.symmetric_difference(b) # 对称差集 返回两个集合中不重复的元素集合
{1, 2, 3, 4}
>>> a ^ b
{1, 2, 3, 4}
>>> c = a & b # c是a和b的交集
>>> c.issubset(a) # 判断c是否为a的子集
True
>>> c <= a
True
>>> c.issuperset(a) # 判断c是否是a的超集
False
>>> c >= a
False
>>> a.copy()
{1, 2, 'jzx'}
>>> a.copy() is a
False
注:集合是可变的,不能作为字典的键。集合只能包含不可变的值,因此不能包含其他集合,对此采用frozenset表示不可变的
>>> a = set()
>>> b = set()
>>> a.add(b) # 错误写法
>>> a.add(frozenset(b)) # 正确写法
堆
一种优先队列,可以任意顺序添加对象。
heappush(heap, x) # 将x压入堆
heappop(heap) # 弹出堆中最小的元素
heapify(heap) # 让列表具备堆特征
heapreplace(heap, x) # 弹出最小的元素,并将x压入堆
nlargest(n ,iter) # 返回iter中n个最大的元素
nsmallest(n, iter) # 返回iter中n个最小的元素
heappush添加元素,不能用于普通列表,只能用于各种堆函数创建的列表(因为顺序很重要)
例:
>>> from heapq import *
>>> from random import shuffle
>>> data = list(range(10))
>>> shuffle(data)
>>> heap = []
>>> for n in data:
heappush(heap, n)
>>> heap
[0, 1, 2, 3, 4, 9, 5, 8, 6, 7]
>>> heappush(heap, 0.5)
>>> heap
[0, 0.5, 2, 3, 1, 9, 5, 8, 6, 7, 4]
>>> heappop(heap)
0
>>> heappop(heap)
0.5
>>> heap = [5, 8, 0, 3, 6, 7, 9, 1, 4, 2 ]
>>> heapify(heap) # 使列表具有堆特征
>>> heap
[0, 1, 5, 3, 2, 7, 9, 8, 4, 6]
双端队列(double-ended queue)
>>> from collections import deque
>>> q = deque(range(5))
>>> q.append(5) # 队尾加元素5
>>> q.appendleft(6) # 对头(左)加元素6
>>> q
deque([6, 0, 1, 2, 3, 4, 5])
>>> q.pop() # 弹出队尾
5
>>> q.popleft() # 弹出对头(左)
6
>>> q
deque([0, 1, 2, 3, 4])
>>> q.rotate(3) # 右三个元素与前面的元素整体位置互换 默认1
>>> q
deque([2, 3, 4, 0, 1])
>>> q.rotate(-1) # 左一个元素与后面的元素整体位置互换 负数表示左起
>>> q
deque([3, 4, 0, 1, 2])
>>> q.count(1) # 统计元素1的个数
1
>>> q.remove(1) # 移除元素1
>>> q
deque([3, 4, 0, 2])
>>> q.reverse() # 队列翻转
>>> q
deque([2, 0, 4, 3])
>>> p = deque([]) # 创建空双端队列
>>> p.append(10)
>>> p.append(11)
>>> q.extend(p) # 将p队列扩展到q队列尾部
>>> q
deque([2, 0, 4, 3, 10, 11])
>>> q.extendleft(p) # 将p队列扩展到q队列头部
>>> q
deque([11, 10, 2, 0, 4, 3, 10, 11])
>>> p.clear() # 清空
>>> p
deque([])
控制语句
1.条件语句
例:
a = input("输入:")
if int(a) < 10:
print(a)
else:
print(int(a)+1)
2.三元条件运算符
条件为真的值 if (条件表达式) else(条件为假的值)
例:
a = 10
print("小于10" if(a < 10) else "大于等于10")
3.多分支选择结构
if 条件表达式1:
语句1/语句块1
elif 条件表达式2:
语句2/语句块2
……
elif 条件表达式n:
语句n/语句块n
[else:
语句n+1/语句块n+1
]
循环结构
1.while循环
while 条件表达式
循环体
例:
num = 1
while num < 20:
print(num, end=" ")
num += 1
2.for循环
for 变量 in 可迭代对象 #可迭代对象:序列(字符串、列表、元组)、字典
循环体 #迭代器对象、生成器对象
break语句
用于while和for
while True:
if(10 > 1):
print("aa")
break # 循环结束
else:
print("bb")
continue语句
结束本次循环
else语句
while、for可以附带一个else语句(可选),若不含break、continue,则循环
结束后,会执行else语句
while 条件表达式:
循环体
else:
语句块
或
for 变量 in 可迭代对象:
循环体
else:
语句块
循环代码优化
1.减少不必要的内层循环计算
2.尽量使用局部变量
3.连接字符串使用join,而不是+
4.列表元素的插入删除尽量在尾部进行
例:
import time
start = time.time()
for i in range(10000):
result = []
for m in range(10000):
result.append(i*1000+m*1000)
end = time.time()
print("耗时:{0}".format((end-start)))
start1 = time.time()
for i in range(10000):
result = []
c = i*1000
for m in range(10000):
result.append(c+m*1000)
end1 = time.time()
print("耗时:{0}".format((end1-start1)))
结果:
耗时:27.45020818710327
耗时:23.803290605545044
zip()并行迭代
zip()函数对多个序列进行并行迭代,在最短序列“用完”是结束
例:
names = ("jzx", "jxx", "jsh", "xxx")
ages = (18, 17, 20, 22)
jobs = ("doctor", "teacher", "fireman")
for name, age, job in zip(names, ages, jobs):
print("{0}--{1}--{2}".format(name, age, job))
结果:
jzx--18--doctor
jxx--17--teacher
jsh--20--fireman
函数
例:
def test01():
print("jzx")
test01()
例:
def test02():
return 2 # 带返回值
print(test02())
例:
def test03():
print("hello")
c = test03
c()
参数的传递
Python中都是引用传递
1.对“可变对象”进行“写操作”,直接作用于原对象本身
2.对“不可变对象”进行“写操作”,会产生一个新的“对象空间”,并用新的值
填充这个空间
可变对象:
字典、列表、集合、自定义对象等
不可变对象:
数字、字符串、元组、function等
传递可变对象的引用
例:
b = [10, 20]
def f(m):
print("m", id(m))
m.append(30)
f(b) # 在列表后追加元素30
print("b:", id(b))
print(b)
结果:
m 2497514201736
b: 2497514201736
[10, 20, 30]
传递可变对象的引用
不可变参数,如int、float、字符串、元组、布尔值
例;
a = 100
def f(n):
print("n:", id(n))
n = n + 10
print("n:", id(n))
print(n)
f(a)
print("a:", id(a))
结果:
n: 140714055331568
n: 140714055331888
110
a: 140714055331568
浅拷贝与深拷贝
浅拷贝:不拷贝子对象的内容,只拷贝子对象的引用,对子对象的修改影响源对象
深拷贝:连子对象全部都拷贝,对子对象的修改不影响源对象
浅拷贝
例:
import copy
a = [10, 20, [5, 6]]
b = copy.copy(a)
print("a:", a)
print("b:", b)
b.append(30)
b[2].append(7)
print("浅拷贝")
print("a:", a) # 对拷贝对象的修改也改变了源对象
print("b:", b)
结果:
a: [10, 20, [5, 6]]
b: [10, 20, [5, 6]]
浅拷贝
a: [10, 20, [5, 6, 7]]
b: [10, 20, [5, 6, 7], 30]
示意:
深拷贝:
例:
import copy
a = [10, 20, [5, 6]]
b = copy.deepcopy(a)
print("a:", a)
print("b:", b)
b.append(30)
b[2].append(7)
print("浅拷贝")
print("a:", a)
print("b:", b)
结果:
a: [10, 20, [5, 6]]
b: [10, 20, [5, 6]]
浅拷贝
a: [10, 20, [5, 6]]
b: [10, 20, [5, 6, 7], 30]
传递不可变对象中含可变对象
例:
a = 10
print("a:", id(a))
def test(m):
print("m:", m)
m = 20
print(m)
print("m:", id(m))
test(a)
结果:
a: 140714170082224
m: 10
20
m: 140714170082544
例:
a = (10, 20, [5, 6]) # 元组不可变,列表可变
print("a:", id(a))
def test(m):
print("m:", m)
m[2][0] = 99
print(m)
print("m:", id(m))
test(a)
print(a)
结果:
a: 2615416816192
m: (10, 20, [5, 6])
(10, 20, [99, 6])
m: 2615416816192
(10, 20, [99, 6])
不可变对象中的可变对象更改后不可变对象不变
默认值参数
例:
def f(a, b, c=10, d=20):
print(a, b, c, d)
f(1, 2)
f(1, 2, 20)
结果:
1 2 10 20
1 2 20 20
命名参数
例:
def f(a, b, c):
print(a, b, c)
f(c=1, b=2, a=20)
结果:
20 2 1
可变参数
1.*param,将多个参数收集到一个“元组”中
2.**param,将多个参数收集到一个“字典”中
例:
def f1(a, b, *c):
print(a, b, c)
f1(1, 2, 3, 4)
def f2(a, b, **c):
print(a, b, c)
f2(1, 2, name="jzx", age=18)
def f3(a, b, *c, **d):
print(a, b, c, d)
f3(1, 2, 3, 4, name="jzx", age=18)
结果:
1 2 (3, 4)
1 2 {'name': 'jzx', 'age': 18}
1 2 (3, 4) {'name': 'jzx', 'age': 18}
强制命名参数
例:
def f(*a, b, c):
print(a, b, c)
f(1, b=2, c=3)
结果:
(1,) 2 3
lambda表达式和匿名函数
例:
f = lambda a, b: a + b
print(f)
print(f(1, 2))
g = [lambda a:a*2, lambda b:b*3, lambda c:c*4]
print(g[0](6), g[1](7), g[2](8)) # 分别向第1、2、3个参数传值6、7、8
结果:
<function <lambda> at 0x000002B5909B27B8>
3
12 21 32
例:
f1 = lambda a, b: a+b
f2 = lambda c, d: c*d
h = [f1, f2] # 函数名为函数对象引用
print(h[0](1, 2))
print(h[1](3, 4))
exec()函数
将字符串作为代码执行,不返回
例:
>>> exec("print('Hello,world')")
Hello,world
eval()函数
计算字符串表示的表达式的值,并返回结果
例:
s = "print('abcd')"
eval(s)
a, b = 10, 20
c = eval("a+b")
print(c)
dict1 = dict(a = 100, b = 200) # 字典 {'a': 100, 'b': 200}
d = eval("a+b", dict1) # 指定上下文
print(d)
结果:
abcd
30
300
嵌套函数:
例:
def print_name(ch, family, name):
def inner_print(a, b): # 隐藏内部函数
print("{0}{1}".format(a, b))
if ch:
inner_print(family, name)
else:
inner_print(name, family)
print_name(1, 'j', 'zx')
global、nonlocal关键字
例:
a = 1
def f():
b = 10
def inner():
nonlocal b # 声明使用外部函数的局部变量
print("inner:", b)
b = 20
global a # 声明使用全局变量
a = 100
inner()
print("b:", b)
f()
print("a:", a)
callable()函数
判断是否可以调用
LEGB规则
Python在查找变量的时候,按如下顺序:
Local -> Enclosed -> Global -> Built in
Local:函数或类的方法内部
Enclosed:嵌套函数内
Global:模块中的全局变量
Built in:Python为自己保留的特殊名称
类
例:
class Student:
school = "njupt" # 类属性,一般都已初始化
city = "nj" # 类属性
def __init__(self, name, score):
# 构造函数固定为__init__() 第一个参数必须是self
self.name = name # 实例属性
self.score = score # 实例属性
Student.city = 'js' + Student.city # 调用类属性
def get_score(self): # 第一个参数必须是self
print("{0}的分数是:{1}".format(self.name, self.score))
def get_school(self):
print("学校是:", Student.school)
def get_city(self):
print("城市:", Student.city)
@staticmethod # 静态方法声明
def add(a, b):
print(int(a+b))
def __del__(self): # 析构方法
print("销毁对象:{0}".format(self))
student = Student("jzx", 99)
student.get_score()
student.get_school()
student.get_city()
Student.add(1, 2) # 通过类名调用静态方法
student.age = 24 # 给student对象随时添加属性,其他实例对象无该属性
print(student.age)
结果:
jzx的分数是:99
学校是: njupt
城市: jsnj
3
24
销毁对象:<__main__.Student object at 0x0000018A30D3F1D0>
__call()__方法和可调用对象
定义了__call()__方法的对象,称为“可调用对象”,即该对象可像函数一
样调用
例:
class Student:
def __call__(self):
return print("小明")
s = Student()
s()
结果:
小明
issubclass(A, B) 判断A类是否为B类的子类
isinstance(A, B) 判断A类是否为B类的实例
类名.__bases__ 查询所有父类
对象.__class__ 查询属于的类
hasattr(A, B) 查询对象A是否有B属性
getattr(A, B, C)
setattr(A, B, C) 设置对象A的B属性为C
@abstractmethod、@classmethod修饰符
Python中没有方法重载
例:
class Student:
def print_name1(self):
print("小明")
def print_name2(a):
print("姓名:{0}".format(a))
Student.name = print_name2
# 动态添加新方法, name指向print_name2函数对象
s = Student()
s.print_name1()
s.name() # 实际是Student.name(s),即print_name2(s)
结果:
小明
姓名:<__main__.Student object at 0x000001C55EAE2B38>
私有属性与私有方法
Python对类的成员没有严格的访问控制,通过约定:
1.两个下划线开头的属性是private,其他为public
2.类的内部可以访问private属性(方法)
3.类的外部不能直接访问private属性(方法)
4.类的外部可以通过“_类名__私有属性(方法)名”访问
注:方法本质上也是属性
例:
class Student:
def __init__(self, name, age):
self.name = name
self.__age = age # 私有实例属性
def __getname(self): # 私有方法
print(self.name)
s = Student("jzx", 24)
print(s.name)
print(s._Student__age) # 访问私有属性
s._Student__getname() # 访问私有方法
结果:
jzx
24
jzx
@property修饰器、get/set方法
例:
class Student:
def __init__(self, name, age):
self.__name = name
self.__age = age
@property # 表示属性本身
def name(self):
return self.__name
@name.setter # 表示对属性的设置
def name(self, name):
self.__name = name
s = Student("jzx", 24)
print(s.name) # 通过方法名直接返回属性
s.name = "jjj" # 通过方法名直接设置属性
print(s.name)
结果:
jzx
jjj
继承
Python中可以多继承,不推荐,排在前面的类的同名方法会覆盖后面
的类的方法
例:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def print_name(self):
print(str(self.name))
class Student(Person):
def __init__(self, name, age, score):
Person.__init__(self, name, age)
self.score = score
s = Student("jzx", 24, 99)
s.print_name()
结果:
jzx
方法重写
例:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def print_name(self):
print(str(self.name))
class Student(Person):
def __init__(self, name, age, score):
Person.__init__(self, name, age)
self.score = score
def print_name(self): # 重写父类方法
print(str("我的名字是:"+self.name))
s = Student("jzx", 24, 99)
s.print_name()
结果:
我的名字是:jzx
类的方法mro()方法或类的属性_mro_可以输出父类与子类的继承关系
例:
class A:
pass
class B(A):
pass
class C(B):
pass
print(C.mro())
结果:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
重写__str__()方法
该方法是Object类的,用于打印对象信息
组合
例:
class A:
def say(self):
print("AAA")
class B:
def __init__(self, s):
self.s = s
a = A()
b = B(a)
b.s.say()
结果:
AAA
使用函数super
例:
class Person:
def __init__(self):
self.legs = 2
class Student(Person):
def __init__(self):
super().__init__()
self.arms = 2
使用property函数
例:
class Rectangle:
def __init__(self):
self.width = 0
self.height = 0
def set_size(self, size):
self.width, self.height = size
def get_size(self):
return self.width, self.height
size = property(set_size, get_size)
>>> r = Rectangle()
>>> r.width = 10
>>> r.height = 5
>>> r.size
(10, 5)
>>> r.size = 150, 100
>>> r.width
150
迭代器
例:
>>> it = iter([1, 2, 3])
>>> next(it)
1
>>> next(it)
2
异常
自定义异常
自定义异常必须直接或间接继承Exception
如:
class MyException(Exception):pass
捕获异常
例:
try:
x = input()
y = input()
print(x/y)
except ZeroDivisionError:
print("除数不能为零")
except TypeError:
print("类型错误")
try:
x = input()
y = input()
print(x/y)
except (ZeroDivisionError, TypeError):
print("除数不能为零或类型错误")
try:
x = input()
y = input()
print(x/y)
except (ZeroDivisionError, TypeError) as e:
print(e)
finally:
模块
模块不是用来执行的,而是用来下定义的,如变量、函数、类等
例:
>>> import sys
>>> sys.path.append('C:/python') # 告知解释器导入的模块的位置(Windows)
>>> sys.path.append('/home/yourusername/python') # (Linux)
例:
# hello.py
def hello():
print("hello world")
>>> import hello
>>> hello.hello() # 调用导入模块的函数
例:
# hello.py
def hello():
print("hello world")
if __name__== '__main__':test() # 若该模块是主程序则执行,否则是普通模块
包
包是一个目录,该目录必须包含文件__init__.py,如果像普通模块一样导入包,文件__init__.py中的内容就是包的内容,导入的就是它
使用dir()函数
打印模块的内容(包括变量、函数、类等)
例:
>>> dir(copy)
['Error', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__spec__', '_copy_dispatch', '_copy_immutable',
'_deepcopy_atomic', '_deepcopy_dict', '_deepcopy_dispatch', '_deepcopy_list',
'_deepcopy_method', '_deepcopy_tuple', '_keep_alive', '_reconstruct', 'copy',
'deepcopy', 'dispatch_table', 'error']
注:根据约定,其中的下划线开头并非供外部使用!
例:
>>> import copy
>>> [n for n in dir(copy) if not n.startswith('_')]
['Error', 'PyStringMap', 'copy', 'deepcopy', 'dispatch_table', 'error', 'name', 't',
'weakref']
使用变量__all__
例:
>>> copy.__all__
['Error', 'copy', 'deepcopy']
# 将只能导入上面三个函数(直接从copy.py复制而来的
# __all__ = ["Error", "copy", "deepcopy"])
>>>from copy import *
>>>from copy import PyStringMap # 其他需显式导入
查看文档
>>> print(range.__doc__)
range(stop) -> range object
range(start, stop[, step]) -> range object
Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
使用源码
>>> import copy
>>> print(copy.__file__)
D:Python3.7.3libcopy.py
获取相关信息
>>> help(copy.copy)
Help on function copy in module copy:
copy(x)
Shallow copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
打开外部程序
>>> import webbrowser
>>> webbrowser.open('http://www.baidu.com')
文件
>>> f = open('file.txt', 'w')
>>> f.write('Hello')
5
>>> f.close()
>>> f = open('file.txt', 'r')
>>> print(f.read(4))
Hell
>>> print(f.read())
o
'r' 读取模式(默认)
'w' 写入模式
'x' 独占模式
'a' 附加模式
'b' 二进制模式(与其他模式结合使用)
't' 文本模式(默认,与其他模式结合使用)
'+' 读写模式(与其他模式结合使用)