Python 学习笔记

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'		文本模式(默认,与其他模式结合使用)
'+'		读写模式(与其他模式结合使用)
原文地址:https://www.cnblogs.com/jiazhongxin/p/12775187.html