python语言基础(傻瓜式文档)

python语言基础

数据存储

思考

思考:为何使用计算机?
为了存储数据、处理数据

思考:数据存在哪里?
数据存储在内存中

思考:内存是怎么存储数据的?
首先要弄清楚怎么存储数字
复制代码

内存

内存:是计算机存储数的介质
抽象内存:一个开关,有两种状态,开启和关闭,一种对应1,一种对应0。把8个开关放到一间房子里,能够称这间房子为“一个字节”,一个开关表明的是一位。每一个房间都有门牌号,看作“地址”。把无数个房间罗列起来组成摩天大厦,能够把摩天大厦当作内存。
复制代码

单位

1bit
8bit      ==    1字节
1024字节  ==    1k
1024k     ==    1M
1024M     ==    1G
1024G     ==    1T
复制代码

进制

二进制:逢2进1
        0 1
        1 + 1 = 10
八进制:逢8进1
        0 1 2 3 4 5 6 7
        1 + 7 = 10
十进制:逢10进1
        0 1 2 3 4 5 6 7 8 9
        1 + 9 = 10
十六进制:逢16进1
        0 1 2 3 4 5 6 7 8 9 a b c d e f
        1 + f = 10
复制代码

进制转换

十进制转二进制
    公式:倒除法,余数逆序
二进制转十进制
    公式:当前的数字(0、1)乘以2的位数次方,在相加
    1001 -> 1 x 2^3 + 0 x 2^2 + 0 x 2^1 + 1 x 2^0 
八进制转二进制
    公式:【一转三位】八进制的一位至关于二进制的三位,计算时按十进制转换,不足三位高位补0
二进制转八进制
    公式:【三位一取】从低位开始,每三位获得一个八进制数字,最后高位不足则补0
十六进制转二进制
    公式:【一转四位】十六进制的一位至关于二进制的四位,计算时按十进制转换,不足四位高位补0
二进制转十六进制
    公式:【四位一取】从低位开始,每四位获得一个十六进制数字,最后高位不足则补0
复制代码

内存中存储的数据

存储数据:
    一、计算机先开辟空间,在存储数据,计算机开辟空间的最小单位是字节
    二、在数据存储时,用最高位标识符号位,0表示正数,1表示复数
复制代码

原码、补码、反码

1    -1

原码:规定了字节数,写明了符号位,获得了数据的原码
    思考:内存是以数据原码的形式存储的吗?

     0000 0000  0000 0000  0000 0000  0000 0001
+    1000 0000  0000 0000  0000 0000  0000 0001
---------------------------------------------------
     1000 0000  0000 0000  0000 0000  0000 0010   -2

    结论:不以原码的形式存储数据

反码:正数的反码就是其原码,负数的反码事其原码的符号位不变其余位取反
    思考:内存是以数据反码的形式存储的吗?
     0000 0000  0000 0000  0000 0000  0000 0001
+    1111 1111  1111 1111  1111 1111  1111 1110
--------------------------------------------------- 
     1111 1111  1111 1111  1111 1111  1111 1111

    结论:不以反码的形式存储数据

补码:正数的补码是其原码(正数三码合一),负数的补码是反码加1
 
     0000 0000  0000 0000  0000 0000  0000 0001
+    1111 1111  1111 1111  1111 1111  1111 1111
---------------------------------------------------  
  1  0000 0000  0000 0000  0000 0000  0000 0000

  加法最后获得的1溢出了,没有存储到内存中
  
    结论:以补码的形式存储数据
复制代码

第一个python程序

# python程序的文件以.py结尾
# python程序的文件名之后最好不要有中文


# 交互模式
# 黑屏终端输入 python 进入交互模式
# 输入 exit() 退出交互模式


# 命令模式
# 输出 将引号内的字符串输出到黑屏终端上
print("sunck is a good man! phone is 13691511443")
# 执行 进入程序所在目录,执行 python 文件名
复制代码

注释

# 单行注释,只能注释一行

# 多行注释
# 根据对象的引用计数器,对象建立会给对象一个引用计数器属性,若是该属性的值为0,那么该对象会被释放。建立了一个字符串对象,可是没有任何的引用,因此计数器为0.
''' print("sunck is a good man") print("sunck is a nice man") '''

""" print("sunck is a cool man") print("sunck is a handsome man") """

print("sunck is a very good man")
复制代码

输入与输出

输入

# 输入:从外部获取变量的值
# input:阻塞,等待输入
name = input()
print("---------------------")
print(name)
复制代码

输出

# 输出:打印到屏幕上一些信息
# 能够接受多个字符串,用逗号分隔
# 在写python程序时切记不要使用中文字符
print("sunck is a good man", "sunck is a nice man", 18)
复制代码

python数据类型

一、Number(数字)
    整数
    浮点数
    复数

二、String(字符串)
    "sunck is a good man"
    'sunck is a nice man'

三、Boolean(布尔值)
    表示真假的值

四、None(空值)

五、list(列表)

六、tuple(元组)

七、dict(字典)

八、set(集合)
复制代码

标识符

标识符的做用:给变量、函数等命名的

什么是标识符:是一串字符串(注意:字符串未必是标识符)

标识符的规则:
    一、只能由字母、数字、下划线组成
    二、开头不能是数字
    三、不能是python的关键字  
        ['False', 'None', 'True', 'and', 'as', 'assert', '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']
    四、区分大小写
    五、见名知意

    注意:在python3中,非ASCII标识符也是容许的了(可是慎用)
''' 复制代码

变量与常量

''' 变量: 概述: 一、程序可操做的存储区名称 二、程序运行过程期间能改变的数据 三、每一个变量都有特定的类型 做用: 将不一样类型的数据存储到内存 定义变量: 变量名 = 数据值 注意:变量在使用前必须先定义,不然会出现错误 删除变量: del 变量名 注意:删除后变量没法引用 '''
# print("num =", num)
age = 18
print("age =", age)
del age
# print("age =", age)

''' 常量:程序运行期间不能改变的数据 '''
复制代码

运算符与表达式

概念

表达式:由变量、常量和运算符组成的式子称为表达式

阅读表达式:
    一、阅读表达式的功能
    二、阅读表达式的值
复制代码

算数运算符与算数运算表达式

''' 算术运算符: + - * / % ** // 加 减 乘 除 取模 求幂 取整 '''
''' 算术运算表达式 功能:进行符号对应的算术运算,不会修改变量的值 值:相关算术运算的结果 '''
num1 = 10
num2 = 3
print(num1 + num2)
print(num1 - num2)
print(num1 * num2)
print(num1 / num2)
print(num1 % num2)
print(num1 ** num2)
print(num1 // num2)
复制代码

赋值运算符和赋值运算表达式

''' 赋值运算符 = '''
''' 赋值运算表达式 格式:变量 = 表达式 功能:计算右侧表达式的值,并赋值给等号左侧的变量 值:赋值结束后变量的值 '''
num3 = 10
num4 = num3 + 2

复制代码

复合运算符

''' 复合运算符: += -= *= /= %= **= //= a += b --> a = a + b a -= b --> a = a - b a *= b --> a = a * b a /= b --> a = a / b a %= b --> a = a % b a **= b --> a = a ** b a //= b --> a = a // b '''
复制代码

位运算符

''' 位运算符: & 按位与运算符:参与运算的两个值,若是两个相应位都为1,则该位结果为1,不然为0 | 按位或运算符:参与运算的两个值,若是两个相应位有一个为1时,则该位结果为1,不然为0 ^ 按位异或运算符:参与运算的两个值,若是两个相应不一样时,则该位结果为1,不然为0 ~ 按位取反运算符:对数据的每一个二进制位进行取反操做,把1变为0,把0变为1 << 左移运算符:运算数的各二进制所有左移若干位,由<<右侧数字指定移动位数,高位丢弃,低位补0 >> 右移运算符:运算数的各二进制所有右移若干位,由>>右侧数字指定移动位数 '''
print(5 & 7)
print(5 | 7)
print(5 ^ 7)
print(~5)
print(2 << 2)
print(11 >> 2)
复制代码

关系运算符与关系运算表达式

''' 关系运算符 == != > < >= <= 等于 不等于 大于 小于 大于等于 小于等于 '''
''' 关系运算表达式 格式:表达式1 关系运算符 表达式2 功能:计算表达式1和表达式2的值 值: 若是关系成立,则整个关系运算表达式的值为真,若是关系不成立,则整个关系运算表达式的值为假 '''
if 1==1:
    print("sunck is a handsome man!")

复制代码

逻辑运算符与逻辑运算表达式

''' 逻辑运算符 逻辑与 逻辑或 逻辑非 '''

''' 逻辑与运算符 and 逻辑与运算表达式 格式:表达式1 and 表达式2 功能:首先计算“表达式1”的值,若表达式1的值为真则计算“表达式2”的值 值: 一、若是表达式1的值为真,表达式2的值为真,则逻辑与运算表达式的值为真 二、若是表达式1的值为真,表达式2的值为假,则逻辑与运算表达式的值为假 三、若是表达式1的值为假,表达式2的值为真,则逻辑与运算表达式的值为假 四、若是表达式1的值为假,表达式2的值为假,则逻辑与运算表达式的值为假 总结:有一个为假就为假 '''
a = 2
b = 1
if a - 1 and b + 1:
    print("sunck is a good man!")
else:
    print("sunck is a nice man!")

复制代码

''' 逻辑或 or 逻辑或运算表达式 格式:表达式1 or 表达式2 功能:首先计算“表达式1”的值,若是表达式1的值为假,则继续计算“表达式2”的值 值: 一、若是表达式1的值为真,表达式2的值为真,则逻辑或运算表达式的值为真 二、若是表达式1的值为真,表达式2的值为假,则逻辑或运算表达式的值为真 三、若是表达式1的值为假,表达式2的值为真,则逻辑或运算表达式的值为真 四、若是表达式1的值为假,表达式2的值为假,则逻辑或运算表达式的值为假 总结:有一个为真就为真 '''
c = 2
d = 1
if c - 1 or print("123"):
    print("sunck is a very good man!")
else:
    print("sunck is a very nice man!")

复制代码

逻辑与、逻辑或的特性

短路原则:
    表达式1 and 表达式2 and 表达式3 and …… and 表达式n
        从左至右依次计算表达式的值,直到遇到某个表达式的值为假就中止计算
    表达式1 or 表达式2 or 表达式3 or …… or 表达式n
        从左至右依次计算表达式的值,直到遇到某个表达式的值为真就中止计算
复制代码

''' 逻辑非 not 逻辑非运算表达式 格式:not 表达式 值: 一、若是“表达式”的值为真,则逻辑非运算表达式的值为假 二、若是“表达式”的值为假,则逻辑非运算表达式的值为真 总结:颠倒黑白 '''
e = 1
if not e:
    print("sunck is a very very good man!")
else:
    print("sunck is a very very nice man!")
复制代码

成员运算符

''' 成员运算符 格式: x in seq x not in seq in:若是在指定的序列中找到值则返回真,不然返回假 not in:若是在指定的序列中没有找打值则返回真,不然返回假 '''
复制代码

身份运算符

''' 身份运算符 格式: obj1 is obj2 obj1 is not obj2 is:判断两个标识符是否引用同一个对象,相同返回真,不然返回假 is not:判断两个标识符是否引用不一样对象,不一样返回真,不然返回假 '''

复制代码

运算符优先级

''' 运算符的优先级: ** 指数 ~ + - 按位取反和一元加减号 * / % // + - 加法减法 << >> & | ^ < > <= >= == != <> = *= /= %= //% += -= **= is is not in not in and or not '''

复制代码

条件控制语句

''' if语句 '''

''' if-else 语句 '''

''' if-elif-else语句 格式: if 表达式1: 语句1 elif 表达式2: 语句2 …… elif 表达式n: 语句n else: 语句e 逻辑:当程序执行到if-elif-else语句时,首先计算“表达式1”的值,若是“表达式1”的值为真,则执行“语句1”,执行完“语句1”则结束整个if-elif-else语句继续向下执行。若是“表达式1”的值为假,则计算“表达式2”的值,若是“表达式2”的值为真,则执行“语句2”,执行完“语句2”则结束整个if-elif-else语句继续向下执行。若是“表达式2”的值为假,则计算“表达式3”的值。如此进行下去,直到某个表达式的值为真为止。若是全部的表达式都为假,且有else语句则执行“语句e” 深入理解(精髓):每个(else if)else都是对它上面全部表达式的否认 '''
''' 从该控制台输入一个年龄 小于0 输入有误 0~1 婴儿 2~6 幼儿 7~14 儿童 15~18 少年 19~30 青年 31~40 壮年 41~50 中年 51~150 老年 151~ 妖精 '''

age = int(input("输入一个年龄:"))
# if age <= 0:
# print("输入错误")
# if age > 0 and age <= 1:
# print("婴儿")
# if age >= 2 and age <= 6:
# print("幼儿")
# if age >= 7 and age <= 14:
# print("儿童")
# if age >= 15 and age <= 18:
# print("少年")
# if age >= 19 and age <= 30:
# print("青年")
# if age >= 31 and age <= 40:
# print("壮年")
# if age >= 41 and age <= 50:
# print("中年")
# if age >= 51 and age <= 150:
# print("老年")
# if age > 150:
# print("妖怪")


# if age <= 0:
# print("输入错误")
# elif age > 0 and age <= 1:
# print("婴儿")
# elif age >= 2 and age <= 6:
# print("幼儿")
# elif age >= 7 and age <= 14:
# print("儿童")
# elif age >= 15 and age <= 18:
# print("少年")
# elif age >= 19 and age <= 30:
# print("青年")
# elif age >= 31 and age <= 40:
# print("壮年")
# elif age >= 41 and age <= 50:
# print("中年")
# elif age >= 51 and age <= 150:
# print("老年")
# else:
# print("妖怪")




if age <= 0:
    print("输入错误")
elif  age <= 1:
    print("婴儿")
elif  age <= 6:
    print("幼儿")
elif  age <= 14:
    print("儿童")
elif  age <= 18:
    print("少年")
elif  age <= 30:
    print("青年")
elif  age <= 40:
    print("壮年")
elif  age <= 50:
    print("中年")
elif  age <= 150:
    print("老年")
else:
    print("妖怪")
复制代码

循环语句(while)

格式与逻辑

''' 格式: while 表达式: 语句 逻辑:当程序执行到while语句时,首先计算表达式的值,若是表达式的值为假,则跳过整个while语句继续向下执行。若是表达式的值为真,则执行语句,执行完语句再计算表达式的值。若是表达式的值为假,则跳过整个while语句继续向下执行。若是表达式的值为真,则执行语句,执行完语句在计算表达式的值,如此循环往复直到表达式的值为假才中止。 '''

复制代码

使用else语句

'''使用else语句 格式: while 表达式: 语句1 else: 语句2 逻辑:在表达式的值为False时执行else语句中的语句2,若是是break结束的循环不走else语句 '''
a = 1
while a < 5:
    print("sunck is a nice man")
    a += 1
else:
    print("sunck is a good man")
复制代码

循环语句(for)

格式与逻辑

''' 格式: for 变量 in 集合: 语句 逻辑:当程序执行到for语句时,按顺序取“集合”中的每一个元素赋值给“变量”,在执行“语句”。如此循环往复,直到取完集合中的元素为止。 '''
复制代码

range函数

# range([startNum,]endNum[, step])
# 列表生成器
# startNum:开始的数字,默认为0
# endNum:结束的数字,不包含在内
# step: 步长,默认为1
# [1,2,3,4,5]
for x in range(1, 6):
    print("x = %d"%x)

复制代码

同时遍历下标和元素

# 同时遍历下标和元素
for index, x in enumerate([1,2,3,4,5]):
    print(index, x)

复制代码

pass语句、continue语句、break语句

pass语句

'''pass语句 做用:当语句要求不但愿任何命令或代码来执行 说明:pass语句时一个空操做,在执行时没有任何响应。pass也是代码最终会用的,可是暂时写不出来 使用在 if语句、while语句、for语句、函数、类等位置 '''
if 1:
    pass
for x in [1,2,3]:
    pass

复制代码

continue语句

'''continue 做用:跳过本次循环快中的剩余语句,而后继续下一次循环 注意:只能跳过距离最近的for或者while '''
for x in [1,2,3,4,5]:
    if x == 3:
        continue
    print("x = %d"%x)
print("-------------------")

# 代码嵌套,层级要明确,嵌套最多在六、7层左右,最好3层
for m in [1,2,3,4,5]:
    print("m = %d"%m)
    for n in [1,2,3,4,5]:
        if n == 3:
            continue
        print("n = %d"%n)
复制代码

break语句

'''break 做用:跳出循环 注意:只能跳出距离最近的for或者while '''
for x in [1,2,3,4,5]:
    if x == 3:
        break
    print("x = %d"%x)
# print("-------------------")
# for m in [1,2,3,4,5]:
# print("m = %d"%m)
# for n in [1,2,3,4,5]:
# if n == 3:
# break
# print("n = %d"%n)


# 循环语句能够有else子句,表达式错误致使循环终止时被执行,但循环被break终止时else语句不执行
index = 0
while index < 3:
    print("index = %d"%index)
    index += 1
    if index == 1:
        break
else:
    print("循环结束了")


print("---------------------------------")
复制代码

深拷贝与浅拷贝

from copy import copy, deepcopy
''' ==:判断的是值 is:判断的是内存地址 '''
# num1 = 300
# num2 = 300
# print(id(num1), id(num2))
# print(num1 == num2)
# print(num1 is num2)

''' 小整数对象:[-5, 256] 最好在python环境中演示,pycharm进行了其余的优化 '''


# a = [1,2,3,4,5,[7,8,9]]
# b = a
# print(b == a)
# print(b is a)
# a[5][1] = 100
# print(a, b)
# print(id(a), id(b))
# print(id(a[5]), id(b[5]))

a = [1,2,3,[4,5,6]]
#深浅拷贝的区分的前提是列表中要有其余列表
#浅拷贝:只拷贝表层元素
# copy
b = copy(a)


#深拷贝:在内存中从新建立全部子元素
# deepcopy
c = deepcopy(a)

a[0] = 100
print(a, b, c)

# print(b == a)
# print(b is a)
# print(c == a)
# print(c is a)
# print(id(a[1]), id(b[1]), id(c[1]))
# print(id(a), id(b), id(c))
# print(id(a[3]), id(b[3]), id(c[3]))
# print(id(a[3][1]), id(b[3][1]), id(c[3][1]))

复制代码

turtle绘图模块

操做

''' 是一个简单的绘图工具 提供了一个小海龟,相似一个机器人,能听懂一些简单的命令 绘图窗口的原点(0,0)在正中间,默认海龟向右侧移动 '''



'''操做命令 一、运动命令 forward(a) 向前移动,a表明距离 backward(a) 向后移动,a表明距离 right(degree) 向右转动degree度 left(degree) 向左转动degree度 goto(x, y) 将笔画(小海龟)移动到坐标(x,y)的位置 speed([speed]) 笔画绘制的速度,范围在[0,10]之间的整数 二、笔画控制命令 up() 笔画抬起,移动时不绘制图形 down() 笔画落下,移动时绘制图形 setheading(degree) 海龟的朝向,degree表明角度 reset() 恢复设置,清空窗口,重置turtle为起始状态 clear() 清空窗口 pensize(width) 笔画的宽度 begin_fill() 开始填充 fillcolor(color) 绘制图形的填充颜色 end_fill() 结束填充 dot(radius, color) 画点 circle(redius, extent, steps) 绘制一个圆形,redius为半径,extent为次数,若是是画圆就没必要写第二个参数 三、其余命令 undo() 撤销turtle上一个动做 hideturtle() 隐藏箭头 showturtle() 显示箭头 write(str, font=(font-name, font-size, font-type)) screensize(x,y) 设置屏幕的宽高 '''
复制代码

Number(数字)

整数

''' 整数: python能够处理任意大小的整数,包含负数 '''
num1 = 10
print(id(num1))
print(type(num1))
# 连续定义
num3 = num4 = num5 = 1
# 交互对称定义
num6, num7 = 1, 2
print(num6, num7)

# 查看数据在内存中的地址
# 小整数对象
num1 = 12
num2 = 13
print(id(num1), id(num2))
num8 = -6
num9 = -6
print(id(num8), id(num9))
复制代码

浮点数

''' 浮点:由整数部分和小数部分组成的 注意:运算可能有四舍五入的偏差 '''
num10 = 0.1
num11 = 0.2
print(num10 + num11)

复制代码

复数

''' 复数:实数部分和虚数部分构成,通常不使用。 '''

复制代码

数学函数

# 求绝对值
num1 = -18
num2 = abs(num1)
print(num2)

# 求多个数中的最大值
print(max(5,3,2,8,6,9,11,3,7))

# 求多个数中的最小值
print(min(5,3,2,8,6,9,11,3,7))

# 求x的n次方
print(pow(2, 4))

# 四舍五入 
# round(x[, n])将浮点数进行四舍五入,若是给出n的值,则表明舍入到小数点的后四位
print(round(3.1415926, 4))

复制代码

math模块

import math
# 向上取整 18.9
print(math.ceil(18.1))
# 向下取整
print(math.floor(18.9))
# 获得浮点数的小数部分和整数部分
print(math.modf(18.5))
# 开平方,数字不能是负数
print(math.sqrt(5))

复制代码

随机数

# 导入随机数模块
import random

复制代码
# 一、choice(seq) 从序列(集合)中随机获取一个元素
print(random.choice([2,4,6,8,10]))

复制代码
# 二、randrange([start, ]stop[, step])
# 做用:从指定范围内,按照指定基数递增的集合中获取一个随机数,基数默认为1
# start-指定范围的开始值,包含在范围内,默认从0开始
# stop-指定范围的结束值,不包含在范围内
# step-指定的基数
print(random.randrange(3)) #[1,2,3,4]

复制代码
# 三、random()
# 随机生成一个实数,范围在[0, 1)之间,获得浮点数
print(random.random())

复制代码
# 四、uniform(x, y)
# 随机生成一个实数,范围在[x, y]之间,获得浮点数,x为随机数的最小值,y为随时的最大值
print(random.uniform(3, 8))

复制代码
# 五、shuffle(list)
# 将序列的元素随机排列
arr = [1,2,3,4,5]
random.shuffle(arr)
print(arr)

复制代码
# 六、randint(start, stop)
# 在指定的范围得到一个整数[start, stop]
print(random.randint(1,5))
复制代码

三角函数

三角函数

#反正弦弧度值
asin(x)
#反正切弧度值
atan(x)
#反余弦弧度值
acos(x)
#x的弧度的余弦值
cos(x)
#x的弧度的正弦值
sin(x)
#x的弧度的正切值
tan(x)
#角度转为弧度
radians(x)
复制代码

数字类型转换

# int(x) 将x转为一个整数
print(int(10.1))
print(int("123"))

复制代码
# float(x)
print(float(10))
print(float("123.34"))

复制代码

字符串

什么是字符串

''' 什么是字符串? 字符串是以单引号或者双引号括起来的任意文本,好比'sunck is a good man'或者"sunck is a nice man"。可是要注意引号自己是一种表现形式,不属于字符串的一部分。 注意:若是字符串自己带双引号 'sunck is a "very" good man' '''

复制代码

建立字符串

#建立字符串
str1 = 'sunck is a good man'
str2 = "sunck is a nice man"

复制代码

字符串运算

'''字符串运算'''
# 字符串拼接
str3 = 'sunck is a good man'
str4 = "sunck is a nice man"
print(str3 + str4)
#重复输出字符串
print(str3 * 3)
# 经过索引下标获取字符串中的字符,索引从0开始(程序员放羊) str[index]
print(str3[1])
# 截取字符串中的一部分 切片编程
print("*"+str3[11:15]+"*")
print("*"+str3[11:]+"*")
print("*"+str3[:15]+"*")
# 判断字符串中是否存在某些内容
print("kaige" in str3)
复制代码

格式化输出字符串

''' 格式化输出(占位符) %s 格式化字符串 %d 格式化整数 %f 格式化浮点数,能够指定小数点后的精度,默认保留小数点后6位 '''
name = "sunck"
age = 18
height = 173.5
# sunck is a good man, he is 18 years old, his height is 173.5cm.
print(name, "is a good man, he is", age, "years old, his height is", height, "cm.")
#若是只有一个替换,能够不写%后面的小括号,可是建议仍是不要省略
print("%s is a good man, he is %d years old, his height is %.2fcm."%(name, age, height))
weight=75
print("*%d*"%(weight))
print("*%5d*"%(weight))
print("*%-5d*"%(weight))
print("*%.5d*"%(weight))
复制代码

经常使用转义字符

''' 经常使用转义字符 反斜杠 \\ 单引号 \'
双引号     \" 换行 \n 横向制表符 \t ''' str5 = '\\' print(str5) str6 = "sunck is a \"very\" good man"
print(str6)
print("sunck is\na good man")
# 若是字符串内部有过个换行,用\n写在一行里很是利于阅读
print("sunck\nis\na\ngood\nman")
print(''' line1 line2 line3 line4 ''')
print("sunck\tgood")
# 若是字符串里面有不少字符须要转义,就须要加入不少\,为了简化,python容许使用r''表示''内部的字符串默认不转义
print('\\\t\\')
print(r'\\\t\\')
复制代码

String内置函数

# eval()
''' 原型:eval(*args, **kwargs) 功能:将字符串当成有效的表达式来求值并返回计算结果 参数: '''
num1 = eval("123")
print(num1)
print(type(num1))
print(eval("+123"))
print(eval("-123"))
print(eval("12+3"))
print(eval("12-3"))
# print(eval("a123"))
# print(eval("12a3"))
abc = "123"
print(eval("abc"))
复制代码
# len(string)
''' 原型: 功能:返回字符串的长度(按字符个数计算) 参数: '''
print(len("sunck is a good man"))
print(len("sunck is a good man凯"))
复制代码
# lower()
''' 原型: 功能:转换字符串中全部的大写字母为小写 参数: '''
str1 = "Sunck Is A Good maN"
str2 = str1.lower()
print(str1, str2)
复制代码
# upper()
''' 原型: 功能:转换字符串中全部的小写字母为大写 参数: '''
复制代码
# swapcase()
''' 原型: 功能:将字符串中大写转为小写,小写转为大写 参数: '''
str3 = "Sunck Is A Good maN"
str4 = str3.swapcase()
print(str3, str4)
复制代码
# capitalize()
''' 原型: 功能:将字符串中第一个字符转为大写,其他转为小写,用于每句话中开始字母大写 参数: '''
str5 = "sunck Is A Good maN"
str6 = str5.capitalize()
print(str5, str6)
复制代码
# title()
''' 原型: 功能:获得“标题化”的字符串,每一个单词的首字符大写,其他小写 参数: '''
str7 = "sunck Is A Good maN"
str8 = str7.title()
print(str7, str8)
复制代码
# center(width[, fillchar])
''' 原型: 功能:返回一个指定宽度width的居中字符串,fillchar为填充字符,默认为空格 参数: '''
str9 = "good"
str10 = str9.center(20, "#")
print("*"+str10+"*")

复制代码
# ljust(width[, fillchar])
''' 原型: 功能:返回一个指定宽度width的左对齐字符串,fillchar为填充字符,默认为空格 参数: '''
str11 = "good"
str12 = str11.ljust(20, "#")
print("*"+str12+"*")

复制代码
# rjust(width,[, fillchar])
''' 原型: 功能:返回一个指定宽度width的右对齐字符串,fillchar为填充字符,默认为空格 参数: '''

复制代码
# zfill (width)
''' 原型: 功能:返回指定宽度width的右对齐字符串,填充0 参数: '''
str13 = "good"
str14 = str13.zfill(20)
print("*"+str14+"*")


复制代码
# count(str[, beg= 0,end=len(string)])
''' 原型: 功能:返回str在string里面出现的次数,若是beg或者end指定则返回指定范围内str出现的次数 参数: '''
str15 = "sunck"
str16 = "sunck is a good man! sunck is a nice man"
print(str16.count(str15,0,20))

复制代码
# find(str[, beg=0 end=len(string)])
''' 原型: 功能:检测str是否包含在string中,若是指定beg和end,则检测指定范围内是否包含。若是包含返回第一个开始的索引值,不然返回-1 参数: '''
str17 = "sunck"
str18 = "cool"
str19 = "aaasunck is a good man! sunck is a nice man"
res = str19.find(str18)
print(res)

复制代码
# index(str[, beg=0, end=len(string)])
''' 原型: 功能:跟find()同样,区别在于若是str不存在会报异常 参数: '''
str20 = "sunck"
str21 = "cool"
str22 = "aaasunck is a good man! sunck is a nice man"
res = str22.index(str20)
print(res)

复制代码
# rfind(str[, beg=0,end=len(string)])
''' 原型: 功能:相似于find(),只不过从右边开始查找 参数: '''

复制代码
# rindex(str[, beg=0, end=len(string)])
''' 原型: 功能:相似于index(),只不过从右边开始查找 参数: '''


复制代码
# lstrip()
''' 原型: 功能:截掉字符串左边指定的字符,默认为空格 参数: '''
str23 = " sunck is a good man"
str24 = str23.lstrip()
print(str23)
print(str24)
str25 = "*****sunck is a good man"
str26 = str25.lstrip("*")
print(str25)
print(str26)


复制代码
# rstrip()
''' 原型: 功能:截掉字符串右边指定的字符,默认为空格 参数: '''


复制代码
# strip([chars])
''' 原型: 功能:在字符串上执行lstrip和rstrip 参数: '''
str27 = "*****sunck is a good man**"
str28 = str27.strip("*")
print(str27)
print(str28)


复制代码
# split(str="", num=string.count(str))
''' 原型: 功能: 参数: '''
str29 = "sunck#is#a#good#man"
wordList = str29.split("#")
print(wordList)
print(type(wordList))

复制代码
# splitlines([keepends])
''' 原型: 功能:按照行('\r','\r\n','\n'),若是keepends为False,不包含换行符,不然保留换行符 参数: '''
str30 = '''good nice cool handsome '''
wordList2 = str30.splitlines()
print(wordList2)

复制代码
# join(seq)
str31 = " ".join(wordList)
print(str31)
''' 原型: 功能: 参数: '''

复制代码
# max(str)
''' 原型: 功能:返回字符串中最大的字母 参数: '''
str32 = "sunck is a good man"
print(max(str32))

复制代码
# min(str)
''' 原型: 功能:返回字符串中最小的字母 参数: '''


复制代码
# replace(old, new [, max])
''' 原型: 功能:将字符串中的old替换成new,若是max指定,则替换不超过max次 参数: '''
str33 = "sunck is a good man, sunck is a nice man, sunck is a cool man"
str34 = str33.replace("sunck", "kaige")
print(str34)


复制代码
# maketrans()
''' 原型: 功能:建立字符映射的转换表,对于接受两个参数的,第一个是字符串,表示要转换的字符,第二个也是字符串表示转换的目标 参数: '''
t = str.maketrans("ag", "12")



复制代码
# translate(table)
''' 原型: 功能:根据str给出的表转换字符串 参数: '''
str35 = "sunck is a good manag"
print(str35.translate(t))



复制代码
# isalpha()
''' 原型: 功能:若是字符串至少有一个字符而且全部的字符都是字母返回True,不然返回假 参数: '''
print("".isalpha())
print("abc".isalpha())
print("abc12".isalpha())



复制代码
# isalnum()
''' 原型: 功能:若是字符串至少有一个字符而且全部的字符都是字母或数字返回True,不然返回假 参数: '''
print("".isalnum())
print("abc".isalnum())
print("abc12".isalnum())



复制代码
# isupper()
''' 原型: 功能:若是字符串至少有一个字符而且全部的字母都是大写字母返回True,不然返回假 参数: '''
print("sunck".isupper())
print("SUNCK".isupper())
print("SUNCK#$%".isupper())
print("SUNCK123".isupper())
print("".isupper())



复制代码
# islower()
''' 原型: 功能:若是字符串至少有一个字符而且全部的字母都是小写字母返回True,不然返回假 参数: '''



复制代码
# istitle()
''' 原型: 功能:若是字符串是标题化的返回True,不然返回False 参数: '''



复制代码
# isdigit()
''' 原型: 功能:若是字符串只包含数字返回True,不然返回False 参数: '''
print("".isdigit())
print("123".isdigit())
print("abc123".isdigit())



复制代码
# isnumeric()
''' 原型: 功能:若是字符串只包含数字返回True,不然返回False 参数: '''



复制代码
# isdecimal()
''' 原型: 功能:检测字符串是否只包含十进制数字 参数: '''



复制代码
# isspace()
''' 原型: 功能:若是字符串中只含有空格则返回True,不然返回False 参数: '''
print("".isspace())
print(" ".isspace())
print(" a".isspace())
print("\t".isspace())
print("\n".isspace())

print("--------------------")



复制代码
# startswith(str[, beg=0,end=len(string)])
''' 原型: 功能:检查字符串是否以str开头,是则返回True, 不然返回False。若是指定了beg和gend,则在指定范围内检查 参数: '''
str40 = "sunck is a good man"
print(str40.startswith("good"))



复制代码
# endswith(suffix[, beg=0, end=len(string)])
''' 原型: 功能:检查字符串是否以suffix结尾,是则返回True, 不然返回False。若是指定了beg和gend,则在指定范围内检查 参数: '''


复制代码
# encode(encoding='UTF-8',errors='strict')
''' 原型: 功能:以encoding指定的编码格式进行编码,若是出错默认报一个ValueError异常,除非errors指定的是igonre或者replace 参数: '''
str41 = "凯哥是一个好男人"
str42 = str41.encode()
str43 = str41.encode("GBK") #gb2312
print(str41)
print(str42)
print(str43)


复制代码
# bytes.decode(encoding="utf-8", errors="strict")
''' 原型: 功能:解码 参数: '''
print(str42.decode("utf-8"))
print(str43.decode("GBK"))


复制代码
# ord()
''' 原型: 功能:获取字符的整数表示 参数: '''
print(ord("A"))
print(ord("凯"))


复制代码
# chr()
''' 原型: 功能:把数字编码转为对应的字符 参数: '''
print(chr(65))
print(chr(20975))



复制代码
# str()
''' 原型: 功能:转成字符串 参数: '''
print(str(123))
print(str(123.1))
print(type(str(True)))



复制代码

布尔值和None

做用:做为真假的判断
''' b = True c = False print(b, c) print(type(b), type(c)) 复制代码
''' 空值:是python里一个特殊的值,用None表示。None不能理解为0,由于0是有意义的,而None是一个特殊的控制,没有实际意义。 做用:定义个变量时,不知道初始值要赋值成什么,那么就赋值为None,当有肯定值在进行赋值操做。 '''
d = None
print(d)
print(type(d))


复制代码

list列表

概述

''' 问题:存储5我的的年龄,求他们的平均年龄 '''
age1 = 18
age2 = 19
age3 = 20
age4 = 21
age5 = 22
print((age1+age2+age3+age4+age5)/5)

''' 问题:存储100我的的年龄,求他们的平均年龄 解决:使用列表 列表本质:是一种有序的集合 '''


复制代码

建立列表

'''建立列表 格式: 列表名 = [列表选项1, 列表选项2, ……, 列表选项n] '''
# 建立空列表
list1 = []

# 建立带有元素的列表
# 列表中的元素的数据类型能够不一样
list2 = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, "good", True, None]


复制代码

列表元素访问

''' 列表元素的访问 '''
list3 = [18, 19, 20, 21, 22]
# 取值:列表名[下标]
print(list3[2])
# 替换:列表名[下标] = 新值
list3[2] = 200
print(list3)
# 注意:下标不要越界
# print(list3[5])
# list3[5] = 23
# print(list3)


复制代码

列表操做

''' 列表操做 '''
# 列表组合
list4 = [1,2,3]
list5 = [4,5,6]
print(list4, list5)
print(list4 + list5)
# 列表重复
list6 = [7,8,9]
print(list6 * 3)
# in not in
print(1 in [1,2,3])
# 列表截取(切片)
list7 = [1,2,3,4,5,6,7,8,9,0]
print(list7[2])
print(list7[1:4])
# -1表示的是最后一个元素的下标, -2倒数第二个元素的下标
print(list7[1:-1])
print(list7[4:])
print(list7[:4])

复制代码

二维列表

''' 二维列表:列表中元素是一维列表 本质:一维列表 '''
list8 = [[1,2,3],
         [4,5,6],
         [7,8,9]]
print(list8)
print(list8[1][1])

复制代码

列表方法

# append(obj)
# 在列表的末尾添加一个新的元素
list1 = [1,2,3,4,5]
list1.append([9,8,7])
print(list1)

复制代码
# extend(seq)
# 在列表末尾一次性追加多个元素
list2 = [1,2,3,4,5]
list2.extend([9,8,7])
print(list2)


复制代码
# insert(index, obj)
# 将元素出入列表,不会覆盖原元素,原元素按顺序后移
list3 = [1,2,3,4,5]
list3.insert(2, 100)
print(list3)


复制代码
# pop(obj=list[-1])
# 移除列表中指定下标处的元素,默认删除最后一个元素
list4 = [1,2,3,4,5]
list4.pop()
# list4.pop()
print(list4)


复制代码
# remove(obj)
# 移除列表中的某个值的第一个匹配项
list5 = [1,2,3,4,5,3]
list5.remove(3)
print(list5)


复制代码
# clear()
# 清空列表
list6 = [1,2,3,4,5,3]
list6.clear()
print(list6)


复制代码
# index(obj)
# 从列表中找出某个值第一个匹配项的下标
list6 = [1,2,3,4,5,3]
print(list6.index(3))


复制代码
# len(list)
# 返回列表中元素的个数
list7 = [1,2,3,4,5,3]
print(len(list7))


复制代码
# count(obj)
# 统计某个元素在列表中出现的次数
list7 = [1,2,3,4,5,3]
print(list7.count(3))


复制代码
# max(list)
# 返回列表中元素的最大值


复制代码
# min(list)
# 返回列表中元素的最小值


复制代码
# reverse()
# 倒序列表中元素
list8 = [1,2,3,4,5,3]
list8.reverse()
print(list8)


复制代码
# sort([func])
list9 = [4,7,1,3,9,5]
list9.sort()
list9.reverse()
print(list9)


复制代码
# list(seq)
# 转为列表 字符串、元组、集合
print(list("sunck"))


复制代码

tuple(元组)

概述

''' 元组 本质:是一种有序集合 特性: 一、与列表很是相似 二、一旦初始化就不能修改 三、使用小括号 '''


复制代码

建立元组

#建立元组: 元组名 = (元组选项1, 元组选项2, ……, 元组选项n)
#建立空元组
t1 = ()
print(t1)
# 定义带元素的元组
# 元素类型能够不一样
t2 = (1,2,3,4,5,"good")
print(t2)
# 定义含有一个元素的元组
# 注意:加个逗号
t3 = (1,)
print(t3)

复制代码

元组的访问

''' 元组元素的访问 '''
#取值 元组名[下标]
t4 = (1,2,3,4,5)
print(t4[1])
# print(t4[5]) #下标越界
print(t4[-1])
print(t4[-5])
# print(t4[-6]) # 下标越界
#修改元组,元组的元素不能修改,可是元素若是是个列表那么能够修改这个列表
t5 = (1,2,3,4,5,[6,7,8])
# t5[5] = [8,7,6]
t5[5][1] = 100
print(t5)

复制代码

元组的操做

'''元组的操做'''
#元祖的组合
t6 = (1,2,3)
t7 = (4,5,6)
print(t6 + t7)
#元组重复
print(t6 * 3)
# 元组截取(切片)
# 与列表、字符串向相似
t8 = (1,2,3,4,5,6,7,8,9)
print(t8[2:7])


复制代码

元组方法

'''元组的方法'''
# len(tuple)
# 返回元组的元素个数
t9 = (1,2,3)
print(len(t9))

# max(tuple)
# min(tuple)

# tuple(seq)
# 将集合转为元组
l = [1,2,3,4,5,6]
t10 = tuple(l)
print(t10)


复制代码

dict(字典)

概述

''' 使用键-值对(key-value)的形式存储数据,具备极快的查找速度 能够的特性: 一、字典中的key必须惟一 二、key必须是不可变对象 a、字符串、整数等都是不可变的,能够做为key b、列表时可变的,不能做为key 三、key通常为字符串 思考:保存一个学生的基本信息(姓名、性别、年龄、升高、体重) stu1 = ["sunck", "男", 18, 173.5, 75] stu2 = ["男", "liudehua", 72, 55, 173] 解决:使用字典 注意:字典中的键值对是无序的 '''


复制代码

建立字典

# 建立字典存储一个学生的基本信息
# {key1:value,key2:value2,……,keyn:valuen}
stu1 = {"name": "sunck", "age": 18, "sex": "男", "height": 173.5, "weight": 75}
stu2 = {"name": "liudehua", "age": 55, "sex": "男", "height": 173, "weight": 72}
stus = [stu1, stu2]
print(stu1)


复制代码

访问字典

#元素的访问
stu3 = {"name": "sunck", "age": 18, "sex": "男", "height": 173.5, "weight": 75}
#获取 字典名[key] 字典.get(key)
print(stu3["name"])
# print(stu3["score"]) #获取的键不存在会报错
score = stu3.get("score")
if score:
    print("分数为:%.2f"%score)
else:
    print("学生没有这个属性")


复制代码

字典的添加、删除、遍历

#添加 若是键不存在则增长属性,不然覆盖原数据
stu3["socre"] = 99.99
stu3["height"] = 180
print(stu3)


复制代码
#删除
stu3.pop("socre")
print(stu3)


复制代码
#遍历
stu4 = {"name": "sunck", "age": 18, "sex": "男", "height": 173.5, "weight": 75}
for key in stu4:
    print(key)
print("--------")
for value in stu4.values():
    print(value)
print("--------")
for key, value in stu4.items():
    print(key+": "+str(value))
print("--------")
for index, key in enumerate(stu3):
    print(index, key)


复制代码

list和dict的比较

'''比较list和dict dict 优势:查找和插入的速度极快,不会随着key的增多而下降效率 缺点:须要占用大量的内存,内存浪费过多 list 优势:占用内存空间小,浪费内存不多 缺点:查找和插入的时间会随着元素的增长而增长 '''


复制代码

set(集合)

概述

''' 与dict相似,是一组key的集合(不存储value) 本质:无序和无重复的集合 '''


复制代码

建立

#建立:须要用一个list或者tuple做为输入集合
# 注意列表中的重复元素会被过滤掉
s1 = set([1,2,3,4,5,3,4])
print(s1)
# 列表去重
numList = [1,2,3,5,7,8,3,5,6,8,9]
numList = list(set(numList))
print(numList)


复制代码

添加

#添加
s2 = set([1,2,3,4,5])
# 插入list、字符串、元组的每一个元素
# iterable 可迭代对象
# s2.update("sunck")
# s2.update([6,7,8])
# s2.update((6,7,8))
# 不能直接插入数字
# s2.update(9)
print(s2)


复制代码

删除

#删除
s3 = set([1,2,3,4,5])
# 从左侧开始删除
print(s3.pop())
# 删除对应的元素,若是元素不存在会报KeyError的异常
s3.remove(3)
print(s3)


复制代码

遍历

#遍历
s4 = set([6,2,3,4,5])
for key in s4:
    print(key)
print("------")
for index, key in enumerate(s4):
    print(index, key)


复制代码

交集与并集

#交集与并集
s5 = set([1,2,3])
s6 = set([2,4,3])
# 交集
print(s5 & s6)
# 并集
print(s5 | s6)


复制代码

类型转换

''' list和tuple中的元素不能存在可变对象 list、tuple、string-->set set() tuple、set、string-->list list() list、set、string-->tuple tuple() '''

复制代码

函数

概述

'''认识函数: 在一个完整的项目中,某些代码会被反复使用。那么将某段代码封装成函数,当咱们要使用功能的时候直接调用函数便可 本质:函数是对功能的封装 有点:简化代码结构,增长代码的复用度 '''

复制代码

定义函数

'''定义函数 格式 def 函数名(参数列表): 语句 return 表达式 说明: def:函数代码块以def关键字开头 函数名:遵照标识符的规则 ():参数列表的开始和结束 参数列表:是函数的调用者给函数的信息,多个信息之间用逗号分隔,若是没有信息,那么小括号中什么都不用写(注意此时小括号不能省略)(形参) 冒号:函数的内容以冒号起始,而且锁紧 语句:函数封装的功能 return:通常用于结束函数,并返回给函数的调用者一些信息。“表达式”就是要返回的数据。若是没有显示的去写return语句,默认return回None 注意: 定义函数时,程序是不会执行函数,当调用函数时才会执行 '''

# def gaolei(money):
# pass

复制代码

使用函数

'''使用函数 格式: 函数名(参数列表) 说明: 函数名:要使用某个功能函数的名字 ():参数列表的开始和结束 参数列表:调用者给函数的信息(实参) 函数调用的本质:实参给形参赋值的过程 '''

复制代码

函数参数

# 编写函数,给函数一个名字,一个年龄,一些爱好,在函数中进行打印
# sunck 18 pwoer、money、book

#形式参数(形参):变量
#参数的数量理论上是无限制的,可是实际中最好不要超过六、7个,参数是类型没有限制
def func(name, age, hobby):
    print("%s is a good man! he is %d years old! he like %s、%s and %s"%(name, age, hobby[0], hobby[1], hobby[2]))

#函数在调用时,须要给函数按顺序传递数据,数量要对应
# 实际参数(实参):是值
func("sunck", 18, ["power", "money", "book"])

复制代码

函数返回值

# 编写函数,实现计算两个数的和
# 注意:在定义的函数体中,尽可能不要常出现print和input
def func(x, y):
    sum = x + y
    return sum #将结果返回到调用函数的位置,返回的数据能够是任意类型的数据

# res接收了func函数运算后的返回值
res = func(1, 2)

复制代码

传递参数

# 值传递:传递不可变类型数据
def func(num):
    print(id(num))
    num = 10
    print(id(num))
a = 20
print(id(a))
func(a)
print(a)




print("-------------------")
# 引用传递:传递可变类型数据
# 本质仍是值传递,传递的是地址
def func2(arr):
    print(id(arr))
    arr.pop()
    print(id(arr))
li = [1,2,3,4,5]
print(id(li))
func2(li)
print(id(li))
print(li)
复制代码

关键字参数

# -*- coding:utf-8 -*-



#目前为止的要求:函数调用时参数的顺序要与定义时一致
#关键字参数:容许函数调用时参数的顺序与定义时不一致


def func(name, age):
    print("%s is a good man! he is %d years old!"%(name, age))

#使用关键字参数
func(age=18, name="sunck")
复制代码

默认参数

# -*- coding:utf-8 -*-

# 使用默认参数
# 在定义函数时尽可能将默认参数写在最后
def func(name, age=18):
    print("%s is a good man! he is %d years old!"%(name, age))

# 在调用函数时,若是没有传递参数,就使用默认参数的值
func("sunck", 20)

复制代码

不定长参数

# -*- coding:utf-8 -*-


#不定长参数:能处理比当初定义时更多的参数

# 在变量前加了星号,变量会存放全部未命名的变量的参数,若是在函数调用时没有指定参数,他就是个空元组
# 不定长参数在默认参数后面
# def func(name, age, a = 10, *args):
# print("%s is a good man! he is %d years old"%(name, age))
# print(args, type(args))
#
# func("sunck", 18)


# **kwargs
# **表明着键值对字典,和*差很少
# def func(name, age, **kwargs):
# print("%s is a good man! he is %d years old"%(name, age))
# print(kwargs, type(kwargs))
#
# func("sunck", 18, x=1, y=2, z=3)


def func(*args, **kwargs):
    print(args)
    print(kwargs)

func(1,2,3,x=1,y=2,z=3)

复制代码

多个返回值

# -*- coding:utf-8 -*-


# 返回值能够一次性返回多个值
# 游戏中返回任务的坐标
def func():
    return 1,2

x, y = func()
z = func()
print(x, y)
print(z)
# for index, value in enumerate([1,2,3,4,5]):

复制代码

匿名函数

# -*- coding:utf-8 -*-





''' 概念:不在使用def语句这样标准的形式定义函数,使用lambda来建立匿名函数 特定: 一、lambda只是一个表达式,函数体比def简单得多 二、lambda主体是一个表达式而不是代码块,仅能在lambda表达式中封装有限的逻辑 三、lambda函数拥有本身的命名空间,且不能访问自有参数序列以外或全局命名空间里的参数 四、虽然lambda函数看起来只能写一行,去不一样于c和c++的内联函数,后者的目的是调用小函数时不占用栈内存而增长运行效率 格式: lambda [arg1[, arg2[, arg3, ……]]]:expression 使用:做为参数传递,实现回调。简化代码 '''

f = lambda x, y: x + y
ret = f(5, 6)
print(ret)

复制代码

特殊函数

map函数

'''map(fn, lsd) 参数: fn:是一个函数 lsd:集合 功能:将传输的函数fn依次做用到lsd集合中的每一个元素,并把结果做为新的Iterator返回 '''
def chr2int(chr):
    return {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9}[chr]
ret = map(chr2int, "13586")
print(ret)
print(list(ret))

复制代码

reduce函数

'''reduce(fn, lsd) 参数: fn:函数 lsd:集合 功能:传入的fn函数做用在lsd集合中,这个fn函数必须接受两个参数,reduce把结果继续和序列的下一个元素做累计计算 reduce(f, [a, b, c, d])==f(f(f(a,b),c),d) '''
# 求一个序列的和
from functools import reduce
def func(x, y):
    return x + y
res = reduce(func, [1,2,3,4,5])
print(res)



#reduce配合map实现str2int
def str2int(s):
    def chrToint(chr):
        return {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9}[chr]
    def f(x, y):
        return x * 10 + y
    return reduce(f, map(chrToint, s))

res = str2int("13543")
print(res)
print(type(res))

复制代码

filter函数

# -*- coding:utf-8 -*-



''' filter(fn, lsd) 参数: fn:函数 lsd:集合 功能:用于过滤序列,把传入的fn函数依次做用在lsd集合中的每一个元素上,而后根据返回值是True仍是False决定是否保留该元素 '''

li1 = [1,2,3,4,5,6,7,8,9]
# 去掉列表中的全部偶数

#过滤的过程
# for i in li1:
# if i % 2 == 0:
# li1.remove(i)
# print(li1)

#过滤的逻辑
def func(num):
    if num % 2 == 0:
        return False
    return True
res = filter(func, li1)
print(li1)
print(res)
print(list(res))





# 找全部的素数



# 需求:删除列表中是空字符串的元素
li2 = ["a", "", "", "c", " ", " bsg "]
def f(item):
    return item and item.strip()
res = filter(f, li2)
print(list(res))

复制代码

sorted函数

# -*- coding:utf-8 -*-


''' 排序算符:冒泡排序、快速排序、 选择排序、计数器排序…… '''
li = [3,4,1,2,5]


# 对列表进行排序
li1 = [3,4,1,2,5]
li2 = sorted(li1)
print(li2)

# 按绝对值大小排序
li3 = [3,-4,1,-2,5]
# key接收函数来实现自定义的排序
li4 = sorted(li3, key=abs)
print(li4)


#降序排序
li5 = [3,-4,1,-2,5]
li6 = sorted(li5, reverse=True)
print(li6)


# 字符串大小问题
# 原理:获取两个字符的第一个字符进行比较,谁的ASCII值大那么谁就大,若是相同则获取下一位字符比较
# print("abc">"ab")
li7 = ["abc", "awg", "agaerger", "eherth"]
#自定义排序逻辑
def func(x):
    return len(x)
li8 = sorted(li7, key=func)
print(li8)

复制代码

做用域

概述

# -*- coding:utf-8 -*-

''' 做用域:变量能够使用的范围,程序的变量并非在哪一个位置均可以访问的,访问的权限决定于这个变量实在哪里赋值的。 做用域的划分: 一、局部做用域(L) 二、闭包函数外到函数中(E) 三、全局做用域(G) 四、内建做用域(B) 变量查找规则: L->E->G->B,首先在自身做用域中查找,找不到的话依次向上级做用中查找,注意不会向低级做用域中查找 Python中只有模块,类以及函数才会引入新的做用域,其它的代码块(好比if、elif、else、for、while、try、except等)是不会引入新的做用域的。 '''
复制代码

体现做用域

# -*- coding:utf-8 -*-
num = 5
#if不会引入新的做用域
if 1:
    index = 10
    print("num = %d"%num)

print("index = %d"%index)

def func(x, y):
    # 取值的使用
    print("在func中使用num:%d"%num)
    # 定义局部变量
    tmp = 100
    return x + y
print(func(1,2))
#在全局中使用局部变量,找不到的
# print("tmp = %d"%tmp)
复制代码

修改全局变量

# -*- coding:utf-8 -*-



num = 10
def func():
    # 在函数的内部能够直接获取全局变量的值,可是不能直接修改全局变量的值。直接修改至关于定义一个新的局部变量,没有修改到全局变量自己
    # 须要将定义的变量声明成全局变量
    global num
    num = 2
    print("1-----num = %d" % num)

func()
print("2-----num = %d" % num)
复制代码

修改嵌套做用域中的变量

# -*- coding:utf-8 -*-
a = 30
def func():
    # 有global会在nonlocal那里报错,申明为全局的后就没有嵌套的了
    # global a
    # a = 10
    def f():
        #想修改嵌套做用域中的变量,须要将它声明
        # nonlocal a
        # a = 20
        print("1----a = %d"%a)
    f()
    print("2----a = %d"%a)

func()
print("3----a = %d"%a)

复制代码

变量的做用域

# -*- coding:utf-8 -*-

a = 10
def func1():
    b = 20
    def func2():
        c = 30
        return a + b + c
    return func2()


print(func1())

复制代码

利用闭包突破做用域链

# -*- coding:utf-8 -*-


'''闭包 概念:在函数体重定义内部函数,而且使用了外部函数的变量,而后把内部函数给,那么这个内部函数就是闭包 优势:避免污染全局环境,这样就能够在函数体外使用函数体中定义的变量 缺点:数据长期驻留在内存中,形成内存极大的浪费。 '''
a = 10
def func1():
    b = 20
    def func2():
        c = 30
        return a
    return func2


f2 = func1()
print(f2())





def func3():
    b = 40
    def func4():
        return b
    return func4

复制代码

装饰器

概念

# -*- coding:utf-8 -*-

''' 是一个闭包,把一个函数做为参数而后返回一个替代版函数,本质上就是一个返回函数的函数 '''

#在不修改原函数的前提下增长函数的功能,最好的方式是使用装饰器
def func():
    print("sunck is a good man")


def f():
    print("***********")
    func()

复制代码

简单装饰器

# -*- coding:utf-8 -*-

def func():
    print("sunck is a good man")

def wrapper(f):
    def inner():
        print("***********")
        f()
    return inner

# d = wrapper(func)
# d()
func = wrapper(func)
func()

复制代码

复杂装饰器

# -*- coding:utf-8 -*-

# 下不修改say原函数代码的状况下增长say的功能,判断age是否符合常理
def say(name, age):
    return "%s is a good man! he is %d years old"%(name, age)



def wrapper(f):
    def inner(name, age):
        #增长功能
        if age <= 0:
            age = 0
        return f(name, age)
    return inner


say = wrapper(say)

print(say("sunck", -18))
复制代码

使用@符号装饰

# -*- coding:utf-8 -*-
''' python2.4支持使用@将装饰器应用在函数上,只须要再函数定义前加上@装饰器的名称便可 '''
def wrapper(f):
    def inner(name, age):
        #增长功能
        if age <= 0:
            age = 0
        return f(name, age)
    return inner

@wrapper
def say(name, age):
    return "%s is a good man! he is %d years old"%(name, age)

# 至关于 say = wrapper(say)

print(say("sunck", -18))
复制代码

通用装饰器

# -*- coding:utf-8 -*-

def wrapper(f):
    def inner(*args, **kwargs):
        #在这增长功能
        print("no zuo no die")
        res = f(*args, **kwargs)
        #若是要修改原函数的返回值,在这修改
        return res
    return inner



@wrapper
def func(name, age):
    print(name, age)
    return "sunck is a good man"

print(func("kaige", 17))

@wrapper
def func2(height):
    print(height)
    print("**********")
func2(111)

复制代码

参数装饰器

# -*- coding:utf-8 -*-

def wrapper(count=3):
    def deco(f):
        def inner(*args, **kwargs):
            for i in range(count):
                f(*args, **kwargs)
        return inner
    return deco

@wrapper()
def func():
    print("sunck is a good man")

func()

复制代码

多个装饰器

# -*- coding:utf-8 -*-
def wrapper1(f):
    print("enter wrapper1")
    def inner1(*args, **kwargs):
        print("enter inner1")
        res = f(*args, **kwargs)
        print("exit inner1")
        return res
    print("exit wrapper1")
    return inner1

def wrapper2(f):
    print("enter wrapper2")
    def inner2(*args, **kwargs):
        print("enter inner2")
        res = f(*args, **kwargs)
        print("exit inner2")
        return res
    print("exit wrapper2")
    return inner2

def wrapper3(f):
    print("enter wrapper3")
    def inner3(*args, **kwargs):
        print("enter inner3")
        res = f(*args, **kwargs)
        print("exit inner3")
        return res
    print("exit wrapper3")
    return inner3

''' 装饰时:从距离近的装饰器开始装饰 执行时:从距离远的装饰器内部函数开始执行 '''
@wrapper1
@wrapper2
@wrapper3
def func(x, y):
    return x + y

print("----------------")
func(1, 2)



''' inner3 = wrapper3(func) inner2 = wrapper2(inner3) inner1 = wrapper1(inner2) func = inner1 '''

复制代码

装饰器使用场景

# -*- coding:utf-8 -*-


''' 一、参数、结果检查 二、缓存 三、计数 四、日志 五、统计 六、权限管理 七、重试 '''

#=====================================================================
''' 一、参数检查是否合格 需求:计算年龄平均值,年龄不能为负数 '''
# def warpper(f):
# def inner(*args,**kwargs):
# for i in args:
# if i <= 0:
# print("输入年龄有误")
# return
# res = f(*args,**kwargs)
# return res
# return inner
#
# @warpper
# def avgYears(*args):
# sum = 0
# for i in args:
# sum += i
# av = sum/len(args)
# return av
#
# print(avgYears(10,12,-2))

''' 结果检查 题目:计算两个数的和,结果超过100则给出警告,不然输出两个数的和 '''
# def wrapper(f):
# def inner(a,b):
# res = f(a,b)
# if res > 100:
# print("警告")
# else:
# return res
# return inner
# @wrapper
# def sum(a,b):
# return a+b
# print(sum(100,2))

''' 计数 题目:对函数调用次数统计 '''
# def wrapper(f):
# count = 0
# def inner(*args,**kwargs):
# res = f(*args,**kwargs)
# nonlocal count
# count += 1
# print("函数第%d次调用"%(count))
# return res
# return inner
#
# @wrapper
# def sum(a,b):
# return a+b
#
# @wrapper
# def f():
# print("fanding is a good man")
#
# print(sum(1,2))
# print(sum(4,5))
# f()
# f()

''' 重试 题目:数据库链接重试 '''
# import time
# def retry(count=3,wait=0,exceptions=(Exception,)):
# def deco(f):
# def inner(*args,**kwargs):
# for i in range(count):
# try:
# res = f(*args,**kwargs)
# except:
# time.sleep(wait)
# continue
# else:
# return res
# return inner
# return deco
#
# import random
# @retry(3)
# def conn(ip, port, dbName, passwd):
# num = random.choice([1, 2, 3, 4])
# print("**************", num)
# if num <= 2:
# 10 / 0
#
# conn("","","","")
复制代码

可迭代对象

# -*- coding:utf-8 -*-

''' 概念:能够直接做用于for循环的对象统称可迭代对象(Iterable) 能够直接做用于for循环的数据类型: 一、集合数据类型,如list、tuple、dict、set、string等 二、generator,包含生成器和带yield的generator function 注意:能够使用isinstance()函数判断一个对象是不是Iterable对象 '''

from collections import Iterable

print(isinstance([], Iterable))
print(isinstance({}, Iterable))
print(isinstance((), Iterable))
print(isinstance("sunck", Iterable))
print(isinstance((x for x in range(10)), Iterable))
print(isinstance(100, Iterable))

复制代码

列表生成式

# -*- coding:utf-8 -*-

''' 做用:python内置的很是简单而且强大的能够用来生成list的生成式 '''

# 生成列表
# 缺点:只能生成简单的列表
print(list(range(1, 11)))


# 需求:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 循环生成列表
# 缺点:循环比较繁琐
li = []
for i in range(1, 11):
    li.append(i * i)
print(li)

# 列表生成式生成列表
li2 = [x * x for x in range(1, 11)]
print(li2)


# 列表生成式的for循环后能够加判断
li3 = [x * x for x in range(1, 11) if x % 2 == 0]
print(li3)


# 排列 组合 排列组合
# 使用双层循环,生成全排列
li4 = [m + n for m in "ABC" for n in "123"]
print(li4)





#六位密码全排列
# import string
# cc = 0
# print(type(string.digits))
# password = (a+b+c+d+e+f for a in string.digits for b in string.digits for c in string.digits for d in string.digits for e in string.digits for f in string.digits)

复制代码

生成器

# -*- coding:utf-8 -*-

''' 概念: 经过列表生成式,能够直接建立一个列表。全部的数据都会存到内存中,受内存的限制,列表的容量是有限制的。若是列表中有10000个数据,若是咱们只需访问前几个元素,后面的基本不会访问,那么形成内存极大的浪费。 若是列表中的元素能够按照某种算法推导出来,那么咱们在循环遍历列表时不断推导后面的元素,从而节省大量内存。在python中,这种一边循环一边推导的机制称为生成器(generator) '''


#建立生成器
# 一、修改列表生成式:将列表生成式的[]改成()便可
g = (x  for x in range(1, 6))
print(g)
print(type(g))
#生成器特色:能够经过next()函数得到generator的下一个值
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# # 当全部元素都拿出来后在执行next会获得StopIteration异常
# print(next(g))

#遍历
#原理:generator保存的是算法,每次调用next()就计算生成器下一个元素的值,直到抛出StopIteration错误为止
# while 1:
# print(next(g))
# print("sunck is a goo dman")
# 之后通常都是使用for循环来迭代生成器,不须要关心StopIteration异常
for i in g:
    print(i)

复制代码

函数实现生成器

# -*- coding:utf-8 -*-

''' 推导的算法比较复杂,用列表生成式for循环没法实现的时候能够选择使用函数生成生成器 '''

# 函数是按顺序执行,遇到return语句或者最后一行函数语句就返回。
# 若是想让一个函数变为生成器函数,只需将函数的return改成yield
# 变成generator函数,在每次调用next()的时候,遇到yield语句返回,若是再次执行next(),会从上次返回的yield语句处继续执行
def func():
    yield 0
    print("sunck is a good man")
    yield 1
    print("sunck is a nice man")
    yield 2
    print("sunck is a cool man")
    yield 3

res = func()
# print(res)
# print(type(res))
print(next(res))
print(next(res))
print(next(res))
print(next(res))
# 遇到yield中断,再继续执行没有yield会报错
# print(next(res))

复制代码

斐波那契数列练习

# -*- coding:utf-8 -*-

''' 0, 1,1,2,3,5,8,13, '''

#编写函数实现斐波那契数列
# def fib(count):
# index = 0
# x, y = 0, 1
# while index < count:
# print(y)
# x, y = y, x + y
# index += 1
# fib(5)



# 生成器实现
# def fib(count):
# index = 0
# x, y = 0, 1
# while index < count:
# yield y
# x, y = y, x + y
# index += 1
#
# g = fib(6)
# for i in g:
# print(i)





def fib(count):
    index = 0
    x, y = 0, 1
    while index < count:
        yield y
        x, y = y, x + y
        index += 1
    return "sunck is a good man"

g = fib(6)
# for循环遍历generator时,拿不到generator的return与的返回值
# 若是想拿返回值,必须捕获StopIteration错误,返回值包含在错误对象的value属性中
while 1:
    try:
        ret = next(g)
        print(ret)
    except StopIteration as e:
        print("返回值:", e.value)
        break

复制代码

迭代器

# -*- coding:utf-8 -*-

''' 概述: 一、能够被next()函数调用并返回一个值的对象称为迭代器对象(Iterator) 二、迭代器不但能够做用于for循环,还能够被next()调用 '''

from collections import Iterator
print(isinstance([], Iterator))
print(isinstance({}, Iterator))
print(isinstance("sunck", Iterator))
print(isinstance((x for x in range(1, 5)), Iterator))


#转成Iterator对象
li = [1,2,3,4,5]
# 将可迭代对象转为迭代器
li = iter(li)
print(next(li))
print(next(li))
print(next(li))
print(next(li))
print(next(li))



# 为何list、dict、str、set等数据类型不是Iterator
# Iterator对象表示的是一个数据流,Iterator对象能被一个next()函数调用并返回一个数据 ,直到抛出StopIteration错误。能够把数据流当作是一个有序的序列,可是不肯定这个序列的长度,只能经过next()函数不断计算下一个数据,因此说Iterator的设计是惰性求值的。Iterator能够表示一个无限大的数据流,而list永远不可能存储无限的数据

复制代码

import语句

格式:import module1[, module2[, module3[, module4], ……]]
注意:一个模块只会被导入一次,无论你执行了多少次import,有效的防止导入模块被一次次的执行

使用模块中的内容:
    module.方法/变量/类
复制代码

from...import语句

做用:从模块中导入一个指定的部分
格式:from modulename import name1[, name2[, name3], ……]
复制代码

from...import*语句

做用:把一个模块的全部内容所有导入当前命名空间
格式:from modulename import *
注意:不该该过多的使用,极可能形成变量的冲突
复制代码

__name__属性

每一个模块都一个__name__属性,当其值为"__main__"时,代表该模块自身在运行,不然是被当作模块引入,此时值为模块的名字

做用:模块就是一个可执行的python文件,一个模块被另外一个模块引入,向让模块中的某一程序不执行,咱们能够用__name__属性来使程序隐藏该块代码,当自身执行时在执行该块代码
复制代码

模块概述

在计算机程序的开发过程当中,随着程序代码越写越多,在一个文件里代码就会愈来愈长,愈来愈难以维护
为了编写可维护性的代码,咱们会把不少函数进行分组,分别放到不一样的文件里,这样,每一个文件包含的代码就相对较少,大多数编程语言都是采用这种组织代码的方式。在python中,一个.py文件就称之为一个模块(module)



优势:
    一、提升了代码的可维护性
    二、提升了代码的复用度,编写代码没必要从零开始,当一个模块编写完成,就能够被其余地方引用
    三、引用其余模块,包含python内置模块和第三方模块
    四、避免函数名和变量名等命名的冲突

复制代码

time模块

名词

UTC(世界协调时间):格林尼治时间,世界标准时间。在中国UTC+8
DST(夏令时):是一种为了节约能源而认为规定地方时间的制度,通常在天亮早的夏季将时间提早一小时

复制代码

时间表示形式

一、时间戳
    以整型或者浮点型表示的是一个以秒为单位的时间间隔,这个时间的基础值是1970年1月1日零时开始算
二、元组形式
    一种python的数据结构表示,这个元组有9个整型元素,分别表示不一样的时间含义
   year
   month(1-12)
   day(1-31)
   hours(0-23)
   minutes(0-59)
   seconds(0-59) 
   weekday(0-6,星期一为0)
   Julian day(1-366):表示当前日期在本年是第几天,day in the year
   DST flag(-1 or 0 or 1):夏令时格式,0表示正常格式,1表示为夏令时格式,-1表示根据当前的日期时间格式来断定
三、格式化字符串
    %a    本地简化星期名称
    %A    本地完整星期名称
    %b    本地简化月份名称
    %B    本地完整月份名称
    %c    本地相应的日期和时间表示
    %d    一个与中的第几天(01-31)
    %H    一天中的第几个小时(24时制,00-23)
    %I    一天中的第几个小时(12时制,01-12)    
    %j    一年中的第几天(001-366)
    %m    月份(01-12)
    %M    分钟数(00-59)
    %p    本地am或者pm的相应符号
    %S    秒(00-59)
    %U    一年中的星期数,以星期天为一个星期
    %w    一个星期中的第几天(0-6, 0表示星期日)
    %W    和%U基本相同,以星期一为一个星期
    %x    本地相应日期
    %X    本地相应时间
    %y    去掉世纪的年份(00-99)
    %Y    完整的年份
    %Z    时区的名字,若是不存在为空字符串

复制代码

方法

# time()
#返回当前的时间戳,浮点数形式,无需传参
t1 = time.time()
print(t1)

复制代码
# gmtime()
# 将时间戳转换为UTC时间元组格式,接收一个浮点型时间戳为参数,若是不传默认值为当前时间的时间戳
t2 = time.gmtime()
print(t2)

复制代码
# localtime()
# 将时间戳转换为本地时间元组格式,接收一个浮点型时间戳为参数,若是不传默认值为当前时间的时间戳
t3 = time.localtime()
print(t3)

复制代码
# mktime()
# 将本地时间元组转为时间戳,接受一个时间元组
t4 = time.mktime(t3)
print(t4)

复制代码
# asctime()
# 将时间元组格式转为字符串形式,接受一个时间元组,默认值为localtime时间的时间元组
t5 = time.asctime(t3)
print(t5)
print(type(t5))

复制代码
# ctime()
# 将时间戳转为字符串,接受一个时间戳,默认值为当前时间戳
t6 = time.ctime()
print(t6)
print(time.asctime(time.localtime()))

复制代码
# strftime()
# 将时间元组以指定的格式转换为字符串形式,接受一个字符串格式化串、时间元组(默认为localtime())
t7 = time.strftime("%Y-%m-%d %X", t3)
print(t7)

复制代码
# strptime()
# 将指定格式的时间字符串解析为时间元组,是strftime逆过程,
t8 = time.strptime("1999-10-01 08:08:08", "%Y-%m-%d %X")
print(t8)

复制代码
# sleep()
# 延迟一个时间段,接收整型或者浮点型

复制代码
# clock()
# 返回当前程序执行时间,Unix系统始终返回所有运行时间,而windows从第二次开始都是以第一次调用此函数的时间戳为基准,而不是以程序开始时间为基准

复制代码

datetime模块

概述

datetime 比 time 高级了很多,能够理解为 datetime 基于time进行了封装,提供了更使用的函数接口,datetime模块的接口更直观、更容易调用

复制代码

模块中的类

模块中的类:
    time      只关注时间
    date      只关注日期
    datetime  同时有时间和日期   
    timedelta 主要用于计算时间跨度
    tzinfo    时区相关

复制代码

方法

# 获取当前时间
t1 = datetime.datetime.now()
print(t1)
print(type(t1))

复制代码
# 获取指定时间
t2 = datetime.datetime(1999, 10, 1, 8, 8, 8, 0)
print(t2)

复制代码
# 将时间转为字符串
t3 = t1.strftime("%Y-%m-%d %X")
print(t3)
print(type(t3))

复制代码
#将格式化字符串转为datetime对象
t4 = datetime.datetime.strptime(t3, "%Y-%m-%d %X")
print(t4)
print(type(t4))

复制代码
# 时间相减,返回一个时间间隔
t5 = datetime.datetime(1999, 10, 1, 8, 8, 8, 0)
t6 = datetime.datetime(1999, 10, 2, 9, 8, 8, 0)
t7 = t6 - t5
print(t7)
print(type(t7))
#间隔天数
print(t7.days)
#除去间隔天数之外的间隔秒数
print(t7.seconds)

复制代码

calendar模块

import calendar

复制代码
#返回指定年的某月
# print(calendar.month(2018, 8))

复制代码
# 返回指定年的日历
# print(calendar.calendar(2018))

复制代码
# 判断某一年是不是闰年
# print(calendar.isleap(2000))

复制代码
#返回某个月的weekday的第一天和这个月的全部天数
# print(calendar.monthrange(2017, 8))

复制代码
#返回某个月以一周为周期的元素序列
print(calendar.monthcalendar(2018, 12))

复制代码

collections模块

namedtuple

概述:
# namedtuple
# 命名元组,本质是一个函数,用它来建立一个自定义的tuple对象
# 规定tuple元素的个数,并能够用属性而不是索来引用tuple中的元素
# 用namedtuple定义一个新的数据类型


复制代码
# 假如这是一个点的坐标,可是没有写注释,过了很久就不知道了
p = (1, 2)
#定义了一个新的数据类型,属于tuple类型的子类型
Point = namedtuple("Point", ["x", "y"])
point = Point(1, 2)
print(isinstance(point, tuple))
print(isinstance(point, Point))
print(point)
print(point[0], point[1])
# 根据属性获取值
print(point.x, point.y)


复制代码

deque

# deque
# 使用list存储数据,按索引访问元素,可是插入和删除元素会根据元素的个数增多而效率下降。由于list是线性存储,数据量大插入和删除效率会低
# deque 就是为了高效实现插入和删除操做的双向列表,适用于队列和栈


复制代码
q = deque([1,2,3,4,5])

q.append(6)
q.appendleft(0)
q.pop()
q.popleft()
print(q)


复制代码

defaultdict

from collections import defaultdict

# 使用dict时,若是引用的key不存在,会抛出KeyError异常。若是但愿key不存在时,能获得一个默认的值,就使用defaultdict

d1 = {"a":1, "b":2, "c":3}
# print(d1["d"])
print(d1.get("d"))


d2 = defaultdict(lambda :"good")
d2["a"] = 1
print(d2)
print(d2["a"])
print(d2["d"])
print(d2.get("d"))


复制代码

OrderedDict

from collections import OrderedDict

#使用dict时,key是无序的。对dict作迭代时没法保证key的顺序。若是须要key有顺序,就能够使用OrderdDict
d1 = {"a":1, "b":2, "c":3}
print(d1)

# 顺序是按照键值对插入的顺序
d2 = OrderedDict([("a",[11, 111]),("c",33),("b",22)])
print(d2)
print(d2["a"])
print(d2.get("a"))


复制代码

Counter

from collections import Counter

# 一个简单的计数器,本质上是dict的一个子类

# 计算集合中每一个元素出现的次数
a = "sunck is a good man"
c = Counter()
print(c)
for ch in a:
    c[ch] = c[ch] + 1
print(c)
结果:
Counter({' ': 4, 's': 2, 'n': 2, 'a': 2, 'o': 2, 'u': 1, 'c': 1, 'k': 1, 'i': 1, 'g': 1, 'd': 1, 'm': 1})


复制代码

uuid模块

概述

概述:
    是128位的全局惟一标识符,一般由32字节的字母串表示,它能够保证时间和空间的惟一性,也称为GUID


复制代码

原理

原理:
    经过MAC地址、时间戳、命名空间、随机数、伪随机数来保证生产的ID的惟一性


复制代码

做用

做用:
    随机生成字符串,当成token使用,当成用户帐号使用,当成订单号使用等(要求不相同字符串)


复制代码

算法

算法:
    一、uuid1()基于时间戳
        有MAC地址,当前时间错,随机数字,能够保证全球范围内的惟一性。可是因为MAC地址的使用时带来安全问题,局域网中能够使用IP来代替MAC
    二、uuid2()基于分布式计算环境DCE
        算法和uuid1相同,不一样的是把时间戳的前四位换位POSIX的UID,实际当中不多使用,注意,Python中没有这个函数
    三、uuid3()基于名字和MD5散列值
        经过计算名字和命名空间的MD5散列值获得的,保证了同一命名空间中不一样名字的惟一性,和不一样命名空间的惟一性,但同一命名空间的相同名字生成相同的uuid
    四、uuid4()基于随机数
        有伪随机数获得的,有必定重复几率的,这个几率而且是能够计算出来的
    五、uuid5()基于名字和SAH1散列值
        算法和uuid3()相同,不一样的是使用SHA1算法
        


复制代码

使用经验

使用经验:
    一、python中没有基于DCE的,因此uuid2()能够忽略
    二、uuid4()存在几率性重复,因为无映射性,最好不用
    三、若是在全局的分布式环境下,最好使用uuid1()
    四、若名字的惟一性要求,最好使用uuid3()或uuid5()


复制代码

用法

print(uuid.uuid1())
print(uuid.uuid4())
print(uuid.uuid3(uuid.NAMESPACE_DNS, "sunck"))
print(uuid.uuid3(uuid.NAMESPACE_DNS, "sunck"))
print(uuid.uuid3(uuid.NAMESPACE_DNS, "kaige"))
print(uuid.uuid5(uuid.NAMESPACE_DNS, "sunck"))


复制代码

base64模块

概述

概述:用记事本打开图片等文件,看到一坨乱码,由于二进制文件包含不少没法显示的内容。因此想让记事本能处理二进制数据,就须要将二进制字符串转换。base64是一种比较常见的二进制编码方法


复制代码

编码原理

编码原理:
    一个包含64个字符的数组
    ['A', 'B', ……, 'a', 'b', ……, '0', '1', ……, '+', '/']
    
    对二进制数据进行处理,每一个三个字节一组,一组就是3x8=24bit,划为4组,每组正好6bit

    获得4个数字做为索引,而后查表,得到相应的4个字符,就是编码后的字符串
    


复制代码

做用

做用:
    适用于小段内容的编码,好比数字证书签名,cookie,网页中传输的少许二进制数据
    


复制代码

注意

注意:base64是一种经过查表的编码方法,不能用于加密,即便修改了字符对照表页不行。


复制代码

使用

#编码
s1 = b"sunck is a good ma"
print(base64.b64encode(s1))
#解码
s2 = b"c3VuY2sgaXMgYSBnb29kIG1h"
print(base64.b64decode(s2))


复制代码

特例

#若是要编码的二进制不是3的倍数,怎么办?
#答:base用\x00字节在末尾补足,在编码的末尾加上1个或2个等号表示补了多少个字节,解码时会自动去掉
s3 = b"sunck is a good man"
print(base64.b64encode(s3))


复制代码
# 因为标准base64编码后可能出现字符+和/,在URL中就不能直接做为参数
# 提供urlsafe_b64encode编码,保证url的安全,将+和/替换成-和_,提供urlsafe_b64decode进行url安全解码
s4 = b"sunck is a good m~"
print(base64.b64encode(s4))
print(base64.urlsafe_b64encode(s4))

s5 = b"c3VuY2sgaXMgYSBnb29kIG1-"
print(base64.urlsafe_b64decode(s5))


复制代码
#因为=字符也可能出如今base64编码中,可是=在url、cookie里面会形成歧义,因此不少base64编码后会把=去掉
s6 = b"abcd"
s8 = base64.b64encode(s6)
print(s8)
# b"abcd" --> b'YWJjZA=='
# b"abcd" --> b'YWJjZA'
s7 = b'YWJjZA=='
print(base64.b64decode(s7))


复制代码
#能够自定义编码对照表列表中64个字符的排序,这样能够自定义编码,可是一般状况下没有任何须要


复制代码

hashlib模块

概述

hashlib 模块提供了常见的摘要算法,如MD5,SHA1

摘要算法(又称哈希算法、散列算法):
    原理:它经过一个函数,把任意长度的数据转为一个长度固定的数据串(一般用16进制的字符串表示)


复制代码

MD5

# 最多见的摘要算法,速度快,一般用32位16进制字符串表示
s1 = b"sunck is a good man"
m5 = hashlib.md5()
m5.update(s1)
print(m5.hexdigest())

#若是数据量比较大, 能够分屡次调用update,最后的结果是同样的
m6 = hashlib.md5()
m6.update(b'sunck is ')
m6.update(b"a good man")
print(m6.hexdigest())


复制代码

SHA1

#SHA1
# 调用SHA1与调用MD5彻底同样,一般用40位16进制字符串表示
s2 = b"sunck is a nice man"
sh1 = hashlib.sha1()
sh1.update(s2)
print(sh1.hexdigest())


复制代码

更安全的

#更安全的
# SHA256
# SHA512
# 越安全的算法不只越慢,并且摘要会越长



#有没有两个不一样的数据经过hash算法后获得了相同的摘要呢?
#有这种可能性,由于摘要算法是将无限多的数据映射到有限的集合中,若是两个数据的摘要相同,称之为碰撞。可能出现,可是很是渺茫


复制代码

总结

应用:
    任何容许用户登录的网站都会存储用户登陆的用户名和密码,那么密码通常存储的是原密码的摘要值。
    
    sunck--good明文存到数据中,若是数据库泄露,全部用户信息会暴露
    
    正确的保存口令方式不是存储明文内容,而是存储口令的摘要,当用户登陆时,首先会计算用户输入的明文口令的摘要,和数据库中的对比,若是一直说明口令正确,不然必定错误。


复制代码

hmac模块

import  hmac

''' 实现HMAC算法,是用一个key对数据进行“杂凑”后在记性的hash,使用hmac比hash算法更安全,不一样的key会产生不一样的hash '''
#对于同一条数据,key不一样会获得不一样的摘要值
s = b"sunck is a good man"
key = b"secret"
h = hmac.new(key, s, digestmod="MD5")
print(h.hexdigest())


复制代码

itertools模块

无限迭代

import itertools
import time
# 无限迭代
# count(start=0, step=1)
# c = itertools.count()
# for i in c:
# print(i)
# time.sleep(1)



# cycle(iterable)
# 把传入的一个序列无限重复下去
# cy = itertools.cycle("sunck")
# for i in cy:
# print(i)
# time.sleep(1)

# repeat(object[, times])
# 把一个元素无限重复下去,若是提供了第二个参数,就能够指定重复次数
# r = itertools.repeat("sunck", 3)
# for i in r:
# print(i)
# time.sleep(1)


复制代码

有限迭代

# 有限迭代
# 把一组迭代对象串联起来,造成一个更大的迭代器
# chain(*iterables)
# cha = itertools.chain("ABC", "abc")
# for i in cha:
# print(i)
# time.sleep(1)
# 把迭代器中相邻的重复元素跳出来放在一块儿
# g = itertools.groupby("AABBBBccdedFFF")
# for key, value in g:
# print(key, list(value))
# time.sleep(1)


复制代码

排列组合

#全排列
# 从n个不一样元素中取出m(m<=n)个元素,按照必定的顺序排成一列,叫作从n个元素中获取m个元素的一个排列。当m==n时,这个排列称为全排列
# itertools.permutations(iterable, length)
# p = list(itertools.permutations([1,2,3,4], 4))
# print(p)
# print(len(p))
''' 5! = 1 * 2 * 3 * 4 * 5 0! = 1 1! = 1 从n个中选m个 n! / (n - m)! 4 1 4!/3! 4 2 4!/2! 4 3 4!/1! 4 4 4!/0! '''


#组合
# 从n个不一样的元素中,任意m(m<=n)个元素为一组,叫作从n个不一样元素中取出m个元素的组合
# itertools.combinations(iterable, length)
# c = list(itertools.combinations([1,2,3,4], 3))
# print(c)
# print(len(c))

''' 4 4 1 4 3 4 4 2 6 4 1 4 n!/m!(n-m)! '''

#排列组合(笛卡尔积)
# itertools.product(*iterable, repeat=1)
# passwds = list(["".join(x) for x in itertools.product("0123456789", repeat=6)])
# print(passwds)
# print(len(passwds))



# passwds = ("".join(x) for x in itertools.product("0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm", repeat=8))
# for i in passwds:
# print(i)
# time.sleep(1)
# 暴力破解
# 枚举破解


复制代码

安装三方模块

''' Windows pip install 模块名 pip install 模块名==版本号 Linux(超级root用户) 超级用户根本就不可能给你用 pip install 模块名 pip install 模块名==版本号 Linux(普通用户) sudo pip install 模块名 sudo pip install 模块名==版本号 '''


复制代码

Pillow模块

from PIL import Image

# pip install Pillow
# 处理图形图像

im = Image.open("1.jpg")
# 打印图片的信息
# print(im.format, im.size, im.mode)
# 设置图片大小
im.thumbnail((100, 80))
#生成新图片
im.save("2.jpg", "JPEG")


复制代码

面向对象

什么是面向对象

自上而下顺序执行,逐步求精;其程序结构是按功能划分为若干个基本模块,这些模块造成一个树状结构;各模块之间的关系尽量简单,在功能上相对独立;每一模块内部均是由顺序、选择和循环三种基本结构组成;其模块化实现的具体方法是使用子程序。程序流程在写程序时就已决定。


把数据及对数据的操做方法放在一块儿,做为一个相互依存的总体——对象。
对同类对象抽象出其共性,造成类。
类中的大多数数据,只能用本类的方法进行处理。
类经过一个简单的外部接口与外界发生关系,对象与对象之间经过消息进行通讯。
程序流程由用户在使用中决定。



复制代码

理解面向对象

面向对象是相对面向过程而言
面向对象和面向过程都是一种思想
面向过程
强调的是功能行为
关注的是解决问题须要哪些步骤 
面向对象
将功能封装进对象,强调具有了功能的对象
关注的是解决问题须要哪些对象 
面向对象是基于面向过程的。

复制代码

面向对象特色

是一种符合人们思考习惯的思想
能够将复杂的事情简单化
将程序员从执行者转换成了指挥者

完成需求时:
先要去找具备所需的功能的对象来用。
若是该对象不存在,那么建立一个具备所需功能的对象。

复制代码

类的定义

生活中描述事物无非就是描述事物的名称/属性和行为。如:人有身高,体重等属性,有说话,打架等行为。Python中用类来描述事物也是如此属性:对应类中的成员变量。行为:对应类中的成员方法。定义类其实在定义类中的成员(成员变量和成员方法) 拥有相同(或者相似)属性和行为的对象均可以抽像出一个类

复制代码

类的设计

只关心3样东西	事物名称(类名):人(Person)	属性:身高(height)、年龄(age)	行为(功能):跑(run)、打架(fight)

复制代码

访问对象方法

# -*- coding:utf-8 -*-

''' 对象方法 经过实例调用时(没法用类名调用),能够引用类内部的任何属性和方法 格式:对象名.方法名(参数列表) 注意:对象方法的第一个参数必须是self,其他参数按顺序排列,调用传参是忽略self self:表明一个对象,哪一个对象调用的对象方法,那么在方法中self就表明哪一个对象 类方法 无需实例化,用类名调用(能够用对象调用),能够调用类的属性和方法,没法取到普通的对象属性和方法,使用@classmethod定义类方法 cls:表示类名 静态方法: 不管用类调用仍是用实例调用,都没法获取到类内部的属性和方法,彻底独立的一个方法,使用@staticmethod定义 总结: 类方法效率要比对象方法高,由于类方法无需实例化对象,而且节省内存,当方法中不涉及对象属性和方法时使用 静态方法通常用做工具方法 '''

class Person(object):
    # 对象方法
    def eat(self, x, y):
        print(self)
        print(self.eat2("a", "b"))
        return "吃%s和%s"%(x, y)
    def eat2(self, x, y):
        return "2吃%s和%s"%(x, y)
    #类方法
    @classmethod
    def run(cls, m):
        print(cls.run2(80))
        return ("跑%d米"%m)
    @classmethod
    def run2(cls, m):
        return ("2跑%d米" % m)
    #静态方法
    @staticmethod
    def play(x):
        return "玩%s"%x
per1 = Person()
per = Person()
print(per, per1)

#调用对象方法
print(per1.eat("苹果", "香蕉"))
#调用类方法
# print(Person.run(200))
#调用静态方法
# print(per.play("球"))
# print(Person.play("麻将"))





class Gongju():
    @staticmethod
    def a():
        pass
    @staticmethod
    def b():
        pass

Gongju.a()
Gongju.b()

复制代码

类属性

# -*- coding:utf-8 -*-

class Person(object):
    #类属性:能够经过类调用,也能够经过对象调用
    # 当类的对象的属性值都同样时就使用类属性
    name = "lilei"
    age  = 20
    height = 170
    weight = 80

#在初始化对象时,每个对象的属性值多相同了
per1 = Person()
per2 = Person()
#经过对象访问属性 对象名.属性名
print(per1.name)
print(per2.name)

#每一个对象拥有本身的属性
per1.name = "hanmeimei"
print(per1.name)
print(per2.name)

print("-------------------")
print(Person.name)


#问题:使用类建立的全部的对象的属性初始值都同样

复制代码

对象的初始状态

# -*- coding:utf-8 -*-

# 需求:在建立对象时给每一个对象直接赋值属性的初始值

# __init__()
# 构造方法,在使用类建立实例对象时自动调用,目的是初始化对象内容。

class Person(object):
    # 后期除非定义单例类,不然基本不用写
    def __new__(cls, *args, **kwargs):
        # 调用父类中的__new__方法开辟内存空间
        return super(Person, cls).__new__(cls)

    #类属性
    def __init__(self, name, age, height, weight):
        # 对象属性,只能对象调用
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    def say(self):
        # 对象方法中能够调用对象属性
        return "my name is %s, I am %d years old"%(self.name, self.age)

#建立对象时给每一个对象的属性赋值
per1 = Person("lilei", 20, 170, 80)
per2 = Person("hanmeimei", 18, 165, 50)

print(per1.name)
print(per2.name)

# print(Person.name) #类中没有name属性,且类名没法调用对象属性


print(per1.say())
print(per2.say())



# 延伸
# __new__()方法:是一个类方法,返回一个对象的实例,在使用类实例化对象时自动调用,目的是在堆区开辟一片内存空间,会在__init__以前调用
# 使用:建立单例类

复制代码

析构函数

# -*- coding:utf-8 -*-

class Person(object):
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight

    # 析构方法,在释放对象时自动调用
    # 做用:释放一些没必要要的内存
    def __del__(self):
        print("object delete")

    def say(self):
        return "my name is %s, I am %d years old"%(self.name, self.age)

per = Person("lilei", 20, 170, 80)
del per

复制代码

访问限制

# -*- coding:utf-8 -*-

class Person(object):
    # 在python中,变量名相似__xxxx__的,属于特殊变量,特殊变量时能够直接访问的,不是私有变量
    def __init__(self, name, age, height, weight, money):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
        # 在python中_xxx变量,这样的实例变量我不是能够直接访问的。可是,按照约定俗成的规定,当看到这样的变量时,意思是虽然我能够被外部直接访问,可是请把我视为私有变量,不要在外部随意访问
        self._temp = 2
        # 特殊变量
        self.__test__ = 1
        #若是要让内部属性不被外部访问,能够把属性的名称前加上两个下划线
        #python中,示例的变量以__开头,就变成了一个私有属性(private),只能在内部访问,外部没法访问
        #不能再外部直接访问__money的缘由是python解释器对外把__money属性改为了_Person__money。因此任然能够用_Person__money来直接访问,可是强烈建议不要这么作,由于不一样版本的python解释器可能会把__money改为不一样的属性名
        self.__money = money



    #定义公有方法间接访问私有属性
    def getMoney(self):
        return self.__money
    def setMoney(self, money):
        if money >= 0:
            self.__money = money

    def say(self):
        return "my name is %s, I am %d years old"%(self.name, self.age)

per = Person("lilei", 20, 170, 80, 100)
per.age = 18
print(per.age)

# print(per.__money)
#间接访问私有属性
per.setMoney(10)
print(per.getMoney())
# print(per._Person__money) #不建议使用
print(per.__test__)
print(per._temp)

复制代码

@property

# -*- coding:utf-8 -*-

class Person(object):
    def __init__(self, name, age, height, weight, money):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
        self.__money = money
    @property
    def money(self):
        return self.__money
    @money.setter
    def money(self, value):
        if value < 0:
            self.__money = 0
        else:
            self.__money = value
    #定义公有方法间接访问私有属性
    # def getMoney(self):
    # return self.__money
    # def setMoney(self, money):
    # if money < 0:
    # self.__money = 0
    # else:
    # self.__money = money
    def say(self):
        return "my name is %s, I am %d years old"%(self.name, self.age)

per = Person("lilei", 20, 170, 80, 100)

# print(per.getMoney())
# per.setMoney(10)
# print(per.getMoney())

per.age = 15
print(per.age)

print("-------------")
#向让访问私有属性的方式相似访问普通属性,须要使用@property
#让私有属性能够使用点语法
print(per.money)  #至关于执行money()方法
per.money = -10
print(per.money)

复制代码

动态给实例添加属性和方法、__slots__槽

# -*- coding:utf-8 -*-
class Person(object):
    __slots__ = ("name", "age", "height", "weight", "money", "run")
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    def say(self):
        return "my name is %s, I am %d years old"%(self.name, self.age)

per1 = Person("lilei", 20, 170, 80)
per2 = Person("hanmeimei", 18, 165, 50)
print(per1.say())

#实例化一个对象后,能够给对象绑定任何的属性和方法,这就是动态语言的灵活性
#若是属性不存在,则变为增长属性
per1.money = 100
print(per1.money)
#增长方法
def run(self):
    print("run")
from types import MethodType
per1.run = MethodType(run, per1)
per1.run()
#注意:给一个实例对象绑定的属性和方法对另外一个实例对象没有影响
# print(per2.money)


#需求:给全部的实例都绑定属性和方法
#解决:给类绑定就能够了
#注意:不只仅给已存在的对象会绑定,未建立的对象也绑定了
Person.faceValue = 100
def play(self):
    print("play")
Person.play = play
print(per1.faceValue, per2.faceValue)
per1.play()
per2.play()
per3 = Person("laowang", 50, 167, 60)
print(per3.faceValue)



#思考:想限制实例的属性,不让对象随意添加属性,只能添加咱们规定一些属性
#解决:在定义类时,顶一个特殊属性__slots__,限制该类实例能添加的属性
# per1.score = 100

复制代码

单例

概述

# -*- coding:utf-8 -*-

''' 单例:是一种软件设计模式,该模式的主要目的是确保一个类只有一个实例存在 实现单例的方式: 一、使用模块 二、使用__new__ 三、使用装饰器 四、使用元类 '''

复制代码

使用--new--()实现单例

# -*- coding:utf-8 -*-

class Card(object):
    def __new__(cls, *args, **kwargs):
        # 每一次实例化的时候,我么都只返回instance同一个对象
        if not hasattr(cls, "instance"):
            cls.instance = super(Card, cls).__new__(cls)
        return cls.instance


card1 = Card()
card1.passwd = "666666"
card2 = Card()
print(card2.passwd)
print(card1 is card2)

复制代码

使用装饰器实现单例

# -*- coding:utf-8 -*-

def singleton(cls):
    instances = {}
    def getinstance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return getinstance


@singleton
class Card(object):
    pass
@singleton
class Person(object):
    pass


c1 = Card()
c2 = Card()
print(c1 is c2)

p1 = Person()
p2 = Person()
print(p1 is p2)

复制代码

重写--repr--和--str--方法

# -*- coding:utf-8 -*-


class Person(object):
    #重写:将继承的方法重写写一遍,在原有的功能基础上添加一些新的功能
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    def say(self):
        return "my name is %s, I am %d years old"%(self.name, self.age)
    #需求:打印该类型的对象时,想打印出对象的各个属性值
    #解决:重写__str__方法
    #__str__()方法:在调用print打印对象时自动调用

    #是显示给用户的
    def __str__(self):
        return "name:%s\nage:%d\nheight:%.2f\nweight:%.2f"%(self.name, self.age, self.height, self.weight)
    #是给机器用的,在python解释器里直接敲对象后回车自动调用
    def __repr__(self):
        return "name:%s\nage:%d\nheight:%.2f\nweight:%.2f"%(self.name, self.age, self.height, self.weight)

per = Person("lilei", 20, 170, 80)
print(per)

复制代码

异常处理、调试、测试

错误处理

# -*- coding:utf-8 -*-



'''概述 在程序运行过程当中,总会遇到各类各样的错误,有的错误时编程代码有问题形成的,这种错误一般称为BUG,BUG是必须修复的。有的错误是用户输入形成的,这种错误的能够经过检查用户的输入来作响应处理。还有一种错误时彻底没法在程序运行过程当中预测的,好比写文件的时候,磁盘满了,写不进去了,再好比从网络中抓取数据,忽然断网了,一般这种状况称为异常,在程序中必需要处理的,不然程序会因各类问题而退出 '''



# 遇到错误,最原始的方式解决方法是事先约定一个错误代码,这样就知道是否有错,在操做系统提供的调用中很是经常使用
''' 缺陷: 一、函数自己返回的数据与错误码会混在一块儿,须要大量的判断是否出错 二、一旦出错,要一级一级上报,直到某个函数能够处理 '''

#错误代码
# print(10 / 0)


#需求:当程序遇到错误时,不让程序结束,而是越过错误继续向下执行
'''try……except……else语句 格式: try: 语句t except 错误表示码 as e: 语句1 except 错误表示码 as e: 语句2 …… except 错误表示码 as e: 语句n else: 语句e 做用:用来检测try语句块中的错误,从而让except语句捕获异常并处理 逻辑: 一、若是try后的“语句t”执行时发生异常,就调回到执行try并执行一个匹配该异常的except子句,异常处理结束,就结束整个try语句(除非处理异常时又引起新的异常) 二、果try后的“语句t”执行时发生异常,可是却没有匹配的except子句,异常提交到上一层try,或者到程序的最上层 三、若是try后的“语句t”执行时没有发生异常,就不会匹配except,若是有else语句,则执行语句e,最后结束整个try语句 '''
# try:
# try:
# print(10 / 1)
# except AttributeError as e:
# print(str(e))
# else:
# print("没有异常")
# except ZeroDivisionError as e:
# print("-----------")
# print("sunck is a good man")

# 特殊使用
#一、使用except而不带任何错误类型,捕获任何异常
# try:
# print(10 / 1)
# except:
# print("有问题")
# else:
# print("没有异常")

#二、使用except而带有多种异常类型,同时匹配多种异常
# try:
# print(10 / 1)
# except (AttributeError, ZeroDivisionError) as e:
# print(str(e))
# else:
# print("没有异常")


#使用注意项
#一、python中的错误其实是类,全部的错误类型都继承自BaseException,因此在使用时注意父类会将子类异常一网打尽
# try:
# print(10 / 0)
# except BaseException as e:
# print("----------1")
# except ZeroDivisionError as e:
# print("----------2")

#二、跨越多层调用,main里调用f2,f2里调用f1,在f1里出错,只要在main里捕获就能够处理了
# def f1(s):
# return 10 / s
# def f2(s):
# return f1(s) + 1
# def main():
# try:
# f2(0)
# except ZeroDivisionError as e:
# print(str(e))
# main()
# print("sunck is a good man")


'''try……except……finally语句 做用:不管try语句块是否发生异常,都将执行finally子句 格式: try: 语句t except 错误表示码 as e: 语句1 except 错误表示码 as e: 语句2 …… except 错误表示码 as e: 语句n finally: 语句f '''
try:
    print(10 / 1)
except ZeroDivisionError as e:
    print("----------2")
finally:
    print("**********")

复制代码

调试(print)

# -*- coding:utf-8 -*-

# 写好的代码能直接运行的几率很是小,总会在不经意间出现更重各样的BUG,有的BUG很简单,看看错误提示就能修改,可是有的BUG分复杂,须要一些调试手段来发现并解决

def func(x):
    print("x = %d"%x)
    return 10 / x

func(0)


# 缺点:未来得删除调试的print,运行结果也会包含一些垃圾信息

复制代码

调试(断言)

# -*- coding:utf-8 -*-

# 使用:凡是用print来辅助调试的 地方,均可以换成断言(assert)语句

#逻辑:当程序执行到assert语句时,首先计算第一个表达式的值,若是表达式的值为真则继续向下执行,不然断言失败,assert语句会抛出AssertionError异常,异常的信息为第二个表达式的值

#缺点:若是将全部的print换成assert也好不到哪里去

#优势:在启动程序时能够经过命令添加-O参数能够关闭assert

def func(x):
    assert x != 0, "x is zero"
    return 10 / x

func(0)

复制代码

调试(logging)

# -*- coding:utf-8 -*-
import logging
#配置输出级别
logging.basicConfig(level=logging.INFO)
''' CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0 '''

#使用:把print替换为logging也能够,和assert相比logging不会抛出错误,而且能够输出到文件


def func(x):
    logging.info("x = %d"%x)
    return 10 / x

func(0)

复制代码

调试(pdb)

# -*- coding:utf-8 -*-

#使用:python的调试器,让程序已单步方式容许(一句一句的运行),能够随时查看运行动态

#以pdb方式调试代码,须要黑屏启动 python -m pdb 文件名


'''调试命令 n:单步执行代码 p 变量名:查看变量 q:退出调试 '''

#缺点:麻烦,若是有10000代码,认为错误可能出如今9000行,须要运行到9000行才行

print("-------------1")
a = 1
print("-------------2")
print("-------------3")
b = 2
print("-------------4")
print("-------------5")
print("-------------6")
print("-------------7")
c = 3
n = 0
print(10 / n)
print("-------------8")
print("-------------9")

复制代码

调试(pdb的自定义开始断点)

# -*- coding:utf-8 -*-

#使用:python的调试器,让程序已单步方式容许(一句一句的运行),能够随时查看运行动态

#以pdb方式调试代码,须要黑屏启动 python -m pdb 文件名


'''调试命令 n:单步执行代码 p 变量名:查看变量 q:退出调试 '''

#缺点:麻烦,若是有10000代码,认为错误可能出如今9000行,须要运行到9000行才行

print("-------------1")
a = 1
print("-------------2")
print("-------------3")
b = 2
print("-------------4")
print("-------------5")
print("-------------6")
print("-------------7")
c = 3
n = 0
print(10 / n)
print("-------------8")
print("-------------9")

复制代码

调试(IDE断点)python

# -*- coding:utf-8 -*-

print("-------------1")
a = 1
print("-------------2")
print("-------------3")
b = 2
print("-------------4")
print("-------------5")
print("-------------6")
print("-------------7")
c = 3
n = "0"
n = int(n)
print(10 / n)
print("-------------8")
print("-------------9")

复制代码

文档测试

# -*- coding:utf-8 -*-
import doctest
#该模块能够直接提取注释中的代码并执行测试


def mySum(x, y):
    #doctest严格按照python交互式命令的输入和输出来判断测试结果是否正确
    ''' >>> print(mySum(1, 2)) 3 '''
    return x + y
print("sunck good")
doctest.testmod()

复制代码

对文件的操做

读文件

# -*- coding:utf-8 -*-
''' 过程: 一、找到文件 二、打开文件 三、读取文件内容 四、关闭文件 '''


#找到文件、打开文件
filePath = r"C:\Users\xlg\Desktop\gp01\day12\code\sunck.txt"
''' 原型: def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True) 参数: file:要打开文件的路径 mode:打开方式 encoding:编码方式 errors:错误处理 返回值: 文件描述符(本质就是一个引用),经过文件描述符能够操做文件 '''
'''打开方式 r 以只读方式打开文件,文件的引用将会放在文件开头 rb 以二进制格式打开只读文件,文件的引用将会放在文件开头 r+ 以读写方式打开文件,文件的引用将会放在文件开头 w 以只写方式打开文件,若是该文件已经存在,则将其内容覆盖,若是不存在则会建立文件 wb 以二进制格式打开只写文件,若是该文件已经存在,则将其内容覆盖,若是不存在则会建立文件 w+ 以读写方式打开文件,若是该文件已经存在,则将其内容覆盖,若是不存在则会建立文件 a 打开一个文件用于追加,若是该文件已经存在,文件的引用将会放在文件的末尾,也就是说新的内容添加到已有内容以后。果不存在则会建立文件进行写入 a+ 打开一个文件用于读写,若是该文件已经存在,文件的引用将会放在文件的末尾,也就是说新的内容添加到已有内容以后。果不存在则会建立文件进行写入 '''

#打开普通文件
fp = open(filePath, "r")
#打开二进制文件
# fp = open(filePath, "rb")
#打开指定编码格式的文件
# fp = open(filePath, "rb", encoding="GBK")
#错误处理:直接忽略
# fp = open(filePath, "rb", encoding="utf-8", errors="ignore")




#读取文件内容

#一、读取文件所有内容
# str1 = fp.read()
# print(str1)

#二、读取指定字节数
# str2 = fp.read(12)
# print("*"+str2+"*")

#三、读取整行,包括"\n"字符
# str3 = fp.readline()
# print(str3+"*")

#四、读取指定字节数
# str3 = fp.readline(12)
# print("*"+str3+"*")

#五、读取全部行并返回列表
# list4 = fp.readlines()
# print(list4)
# print(type(list4))

#读取文件的原理是从文件描述符的位置向后读取
print("-------------", fp.tell())
fp.read()
#查看文件描述符的位置
print("-------------", fp.tell())
#修改文件描述符的位置
fp.seek(1)
str5 = fp.read(12)
print("*"+str5+"*")
str6 = fp.read(2)
print("*"+str6+"*")


#关闭文件:文件使用完后必须关闭,由于文件对象会占用操做系统的资源,而且操做系统同一时间能打开的文件的数量是有限的
fp.close()
复制代码

读文件的完整过程

# -*- coding:utf-8 -*-


try:
    fp = open("sunck.txt", "r")
    #操做文件
finally:
    if fp:
        fp.close()
复制代码

读文件的简写方式

# -*- coding:utf-8 -*-


with open("sunck.txt", "r") as fp:
    print(fp.read())
复制代码

写文件

# -*- coding:utf-8 -*-
import time

'''写文件过程 一、找到文件 二、打开文件 三、将内容写入缓冲区,此时内容没写写入文件 四、刷新缓冲区,直接把缓冲区的数据马上写入文件 刷新缓冲区的方式: a、程序结束 b、关闭文件 c、手动刷新 d、遇到\n e、缓冲区满了 五、关闭文件 '''

filePath = "sunck.txt"
fp = open(filePath, "a")

# 将内容写入缓冲区
fp.write("sunck is a good man!")
# 刷新缓冲区
fp.flush()
# time.sleep(5)

fp.close()



#简单方式
# with open("sunck.txt", "w") as fp1:
# fp1.write("asd")

复制代码

编码与解码

# -*- coding:utf-8 -*-

# 编码
with open("sunck.txt", "wb") as f1:
    info = "sunck is a nice man!凯"
    info = info.encode("utf-8")
    print(info)
    f1.write(info)


# 解码
with open("sunck.txt", "rb") as f2:
    info = f2.read()
    print(info)
    print(type(info))
    info = info.decode("utf-8")
    print(info)
    print(type(info))

复制代码

StringIO和BytesIO

# -*- coding:utf-8 -*-
from io import StringIO
from io import BytesIO

#StringIO
#做用:数据的读写不必定都是文件,也能够在内存中读写,做用是在内存中读写字符串
#写
# fp = StringIO()
# fp.write("sunck")
# fp.write(" ")
# fp.write("is")
# fp.write(" ")
# fp.write("a")
# fp.write(" ")
# fp.write("good")
# fp.write(" ")
# fp.write("man!")
# #获取写入的内容
# info = fp.getvalue()
# print(info)


#读
# fp = StringIO("good\nnice\nhandsome\n")
# print(fp.read())
# print(fp.readline())



#BytesIO
#做用:StringIO只能操做字符串,BytesIO能够操做二进制数据,做用是在内存中读写bytes
#写
# fp = BytesIO()
# fp.write("凯哥".encode("utf-8"))
# print(fp.getvalue())

# 读
# fp = BytesIO(b'\xe5\x87\xaf\xe5\x93\xa5')
# print(fp.read().decode("utf-8"))

复制代码

os模块

# -*- coding:utf-8 -*-
import os

#做用:包含了广泛的操做系统功能,提供了很是丰富的方法来处理文件和目录


#使用


# 操做系统的类型
# nt Windows
# posix Linux、Unix
print(os.name)

# 获取详细的系统信息,linux、Unix下使用
# print(os.uname())

# 获取系统中的环境变量
print(os.environ)
# 获取指定环境变量的值
print(os.environ.get("ALLUSERSPROFILE"))

# 放回当前目录 .
print(os.curdir)

# 获得当前工做目录的绝对路径
print(os.getcwd())

# 返回指定目录下的全部文件和目录 listdir([path]),没有path返回当前工做目录下的
print(os.listdir(r"C:\Users\xlg\Desktop\gp01"))

#建立指定目录
# os.mkdir(r"C:\Users\xlg\Desktop\gp01\day14")

#删除目录
# os.rmdir(r"C:\Users\xlg\Desktop\gp01\day14")

#获取文件属性
# print(os.stat(r"C:\Users\xlg\Desktop\gp01\一、基础内容简介.txt"))

#重命名
# os.rename(r"C:\Users\xlg\Desktop\gp01\day13\code\sunck.txt",r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt")

#删除普通文件
# os.remove(r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt")

#运行shell命令
# os.system("notepad")
# os.system("shutdown -s -t 10")
# os.system("shutdown -a")




#操做文件和目录的函数一部分放在os模块中,还有一部分放在os.path中

#返回指定路径的绝对路径
print(os.path.abspath("."))
#拼接路径
print(os.path.join(r"C:\Users\xlg\Desktop\gp01\day13\abc", "kaige.txt"))
#拆分路径
print(os.path.split(r"C:\Users\xlg\Desktop\gp01\day13\abc\kaige.txt"))
#获取文件扩展名
print(os.path.splitext(r"C:\Users\xlg\Desktop\gp01\day13\abc\kaige.txt"))
#判断是不是目录(得存在),是返回True, 不然返回False,
print(os.path.isdir(r"C:\Users\xlg\Desktop\gp01\day13\code"))
#判断普通文件是否存在,存在返回True, 不然返回False
print(os.path.isfile(r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt"))
#判断文件和目录是否存在
print(os.path.exists(r"C:\Users\xlg\Desktop\gp01\day13\abc"))
#判断是不是绝对路径,(不管是否存在)
print(os.path.isabs(r"C:\Users\xlg\Desktop\gp01\day13\abc"))


#获取文件大小
print(os.path.getsize(r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt"))



#获取文件名
print(os.path.basename(r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt"))
#获得文件路径
print(os.path.dirname(r"C:\Users\xlg\Desktop\gp01\day13\code\kaige.txt"))

复制代码

list、tuple、dict、set的文件操做

# -*- coding:utf-8 -*-

# 持久保存对象,将list、tuple、dict、set等数据进行序列化存储到文件
import pickle

# users = {"666666":{"name":"sunck","idCard":"666666","cards":{"1":{"cardId":"1","passwd":"1","money":"1"}}}}
# with open("users.txt", "wb") as fp:
# pickle.dump(users, fp)


# with open("users.txt", "rb") as fp:
# users = pickle.load(fp)
# print(users)
# print(type(users))

复制代码

递归、深度遍历、广度遍历算法

递归

# -*- coding:utf-8 -*-

''' 递归: 一、自身调用自身造成递归 二、两个函数相互调用造成递归 递推: '''


#递归调用:一个函数,调用自身,称为递归调用
#递归函数:一个会调用自身的函数称为递归函数
#注意:凡是循环能干的事,递归都能干

''' 递归三步走 一、写出临界条件 二、假设当前函数已经能用,调用自身计算上一次的结果,在求出本次结果 三、找这一次和上一次的关系 '''


#在之后的开发中尽可能避免使用递归,容易形成内存泄露,效率也会偏低

#1 + 2 + 3 + 4 + 5
def func(num):
    if num == 1:
        return 1
    return func(num - 1) + num

print(func(5))

''' func(5) func(4) + 5 func(3) + 4 + 5 func(2) + 3 + 4 + 5 func(1) + 2 + 3 + 4 + 5 1 + 2 + 3 + 4 + 5 '''

复制代码

递归遍历目录

# -*- coding:utf-8 -*-

import os
def traverseDir(path, treeShow = ""):
    filesList = os.listdir(path)
    for filename in filesList:
        absPath = os.path.join(path, filename)
        if os.path.isdir(absPath):
            print(treeShow+"目录:"+filename)
            traverseDir(absPath, treeShow + " ")
        else:
            print(treeShow+"文件:"+filename)
traverseDir(r"C:\Users\xlg\Desktop\gp01\day13\file")

复制代码

栈模拟递归遍历目录(深度遍历)

# -*- coding:utf-8 -*-


def traverseDir(path):
    import os
    myStack = []

    myStack.append((path,0))

    while len(myStack) != 0:
        #出栈
        item = myStack.pop()
        filePath = item[0]
        num = item[1]
        treeShow = " " * num
        filesList = os.listdir(filePath)
        for fileName in filesList:
            absPath = os.path.join(filePath, fileName)
            if os.path.isdir(absPath):
                #压栈
                print(treeShow + "目录:" + fileName)
                myStack.append((absPath, num+1))
            else:
                print(treeShow + "文件:" + fileName)

traverseDir(r"C:\Users\xlg\Desktop\gp01\day13\file")

复制代码

队列模拟递归遍历目录(广度遍历)

# -*- coding:utf-8 -*-


def traverseDir(path):
    import os
    from collections import deque

    queue = deque([])

    #进队
    queue.append((path, 0))

    while len(queue) != 0:
        #出队
        item = queue.popleft()
        filePath = item[0]
        num = item[1]
        treeShow = " " * num
        filesList = os.listdir(filePath)

        for fileName in filesList:
            absPath = os.path.join(filePath, fileName)
            if os.path.isdir(absPath):
                #进队
                print(treeShow + "目录:" + fileName)
                queue.append((absPath, num + 1))
            else:
                print(treeShow + "文件:" + fileName)



traverseDir(r"C:\Users\xlg\Desktop\gp01\day13\file")

复制代码

正则

为何使用正则

# -*- coding:utf-8 -*-

#输入一串字符串,判断是不是手机号码

def isPhone(phone):
    # 全都是数字字符
    # 长度为11
    # 以130、131等开头
    pass


# 使用正则会让这个问题简单化

复制代码

re模块概述

# -*- coding:utf-8 -*-


''' python自1.5版本起增长了re模块,该模块提供了Perl风格的正则表达式模式 re模块使python语言拥有了所有的正则表达式功能 三个函数: match() search() findall() '''

复制代码

match函数

# -*- coding:utf-8 -*-
import re

r''' 原型:match(pattern, string, flags=0) 功能:尝试从字符串string的起始位置匹配一个pattern模式,若是匹配成功,返回正则对象,不然返回None。 返回的正则对象中有: start():匹配到的开始索引、end():匹配到的结束索引、string:匹配的字符串、groups():返回括号中匹配到的数据(单个)、span():返回匹配到的起始索引、group():返回匹配到的总体、endpos() 参数: pattern:匹配的正则表达式 string:要匹配的字符串 flags:标志位,用于控制正则表达式的匹配方式(是否大小写、是否多行匹配等等) re.I:使匹配对大小写不敏感 re.L:作本地化识别匹配 re.M:多行匹配,影响^和$ re.S:使.匹配包括换行符在内的全部字符 re.U:根据Unicode字符集解析字符,影响\w、\W、\b、\B re.X:经过给予咱们功能灵活的格式以便更好的理解正则表达式 '''

print(re.match("www", "www.sunck.wang"))
print(re.match("www", "sunck.wangwww"))
print(re.match("www", "Www.sunck.wang", re.I))
ret = re.match("www", "www.sunck.wang")
print(ret.span())

复制代码

search函数

# -*- coding:utf-8 -*-

import re

''' 原型:search(pattern, string, flags=0) 功能:扫描整个字符串string,并返回第一个成功的匹配 参数: '''
print(re.search("www", "www.sunck.wang"))
print(re.search("www", "awww.sunck.wangwww"))

复制代码

findall函数

# -*- coding:utf-8 -*-
import re

''' 原型:findall(pattern, string, flags=0) 功能:扫描整个字符串string并返回结果的列表 '''
print(re.findall(r"ww[12345]","ww1.suwwwnck.wwwaaang"))

返回值:
若是成功,返回匹配到数据的列表([('ww', 'w'), ('ww', 'w')]),若是不成功,返回空链表
# ww1 ww2 ww3 ww4 ww5

复制代码

正则表达式元字符

# -*- coding:utf-8 -*-
import re

# 一、匹配单个字符与数字
''' . 匹配除换行符之外的任意字符,当flags被指定为re.S时能够匹配包含换行符之内的全部字符,若是没有指定,那么不包含换行符[.\n] [] 里面是字符的集合,匹配[]里面任意一个字符 [0123456789] 匹配任意一个数字字符 [0-9] 匹配任意一个数字字符 [a-z] 匹配任意一个小写英文字母字符 [A-Z] 匹配任意一个大写英文字母字符 [a-zA-Z] 匹配任意一个字母字符 [a-zA-Z0-9] 匹任意一个数字或字母字符 [^sunck] []里的^称为脱字符,表示非,匹配不在[]里的任意一个字符。匹配除了 "s" "u" "n" "c" "k"之外任意一个字符 \d 匹配任意一个数字字符 [0-9] \D 匹配任意一个非数字符 [^0-9] \w 匹配字母、下划线、数字 [0-9a-zA-z_] \W 匹配非字母、下划线、数字 [^0-9a-zA-z_] \s 匹配空白符(空格、换页、换行、回车、制表等) [ \f\n\r\t] \S 匹配非空白符 [^ \f\n\r\t] '''








# 二、锚字符
''' ^ 行首匹配,和[]中的^不是一个意思 $ 行尾匹配 '''
# print(re.search(r"^sunck$", "sunck"))


# 二、边界字符
r''' \A 匹配字符串开始,和^的区别是\A只匹配整个字符的开头,即便在re.M模式下,也不会匹配其它的行首 \Z 匹配字符结尾,和$的区别是\Z只匹配整个字符的结尾,即便在re.M模式下,也不会匹配其它的结尾 \b 匹配一个单词的边界,指单词和空格的位置 \B 匹配非单词边界, '''
s = '''sunck is a good man sunck is a nice man sunck is a cool man '''
# print(re.findall(r"\Asunck", s, re.M))
# print(re.findall(r"ck\b", "sunck"))
# print(re.findall(r"ck\b", "suckn"))
# print(re.findall(r"ck\B", "sunck"))
# print(re.findall(r"ck\B", "suckn"))






# 四、匹配多个字符
'''如下使用的x、y、z均为假设的普通字符,n、m表示一个数字,不是正则表达是的元字符 (xyz) 匹配括号内的xyz(做为一个总体去匹配) x? 匹配0个或1个x,非贪婪匹配 x* 匹配0个或任意多个x x+ 匹配至少一个x x{n} 匹配肯定n个x,n是非负整数 x{n,} 匹配至少n个x x{n,m} 匹配至少n个,最多m个x x|y |表示或,匹配x或y '''
print(re.findall(r"(sunck)", "sunck is a good man!sunck is a ncie man"))
print(re.findall(r"a?", "abbbaabbaaa"))
print(re.findall(r"a*", "aaa"))
print(re.findall(r"P|python", "pythonaaaPython"))

复制代码

切分字符串

# -*- coding:utf-8 -*-
import re


str1 = "sunck is a good man!"
# print(str1.split(" "))

print(re.split(r" +", str1))

复制代码

finditer函数

# -*- coding:utf-8 -*-
import re

''' 原型:finditer(pattern, string, flags=0) 做用:相似findall,返回一个迭代器 区别:findall返回全部匹配的字符,并存为一个列表,若是数据过多,占用内存。而finditer并非直接返回找到的全部字符从,而是返回一个迭代器,能够经过next迭代 '''
str1 = "sunck is a good man! sunck is a good man"
res = re.finditer(r"(sunck)", str1)
print(res)
print(type(res))
for x in res:
    print(x)

复制代码

字符串的替换和修改

# -*- coding:utf-8 -*-

import re

''' sub(pattern, repl, string, count=0, flags=0) subn(pattern, repl, string, count=0, flags=0) 做用:在目标字符串string中查找匹配的pattern模式字符,在把它们替换成指定的repl字符串,能够指定最多替换count次,不然替换全部 参数: pattern:正则表达式 repl:指定用来替换的字符串 string:目标字符串 count:最多替换次数 flags: 区别:sub返回一个被替换的字符串,subn返回一个元组,元组的第一个元素为被替换的字符串,第二个元素为发生了多少次替换 '''
str1 = "sunck is a good man!sunck is a nice man!sunck is a cool man"
print(re.sub(r"(sunck)", "kaige", str1))
print(re.subn(r"(sunck)", "kaige", str1))

复制代码

分组

# -*- coding:utf-8 -*-
import re

''' 概念:除了简单的判断是否匹配以外,正则表达式还有提取子串的功能,用()表示的就是要提取的分组 '''

 
#组的排序:从外到内,从左到右
print(m)
# 使用组序号获取匹配的字符串,0表示原数据
print(m.group(0))
#根据名字获取组内容
print(m.group("quhao"))
print(m.group(1))
print(m.group("phone"))
print(m.group(2))
# 查看匹配的各组的数据
print(m.groups())

复制代码

编译

# -*- coding:utf-8 -*-
import re

''' 概念:当在python中使用正则表达式时,re模块会作两件事情,一件是编译正则表达式,若是表达式的字符串自己不合法,会报错。一件是用编译后的正则表达式取匹配字符串 优势:若是一个正则表达式要使用几千遍,每一次都会编译,处于效率的考虑进行正则表达式的编译,这样就不用每次都编译,节省了编译时的时间,提高了效率 '''

#编译正则表达式,获得的是一个正则表达式对象
re_phone = re.compile(r"(?P<quhao>\d{3})-(?P<phone>\d{8})", re.I)



print(re_phone.findall("010-09876543aa010-98789098"))
''' findall(self, string, pos=0, endpos=-1) finditer(self, string, pos=0, endpos=-1) match(self, string, pos=0, endpos=-1) search(self, string, pos=0, endpos=-1) '''


复制代码

贪婪匹配

# -*- coding:utf-8 -*-
import re

''' 概念:匹配尽量多的字符 '''


print(re.match(r"^(\d+?)(0*)$", "120345000").groups())


'''尽量匹配少的字符串 *? +? ?? '''


print(re.findall(r"//*.*/*/", r"/* part1 */ /* part2 */"))
res = re.findall(r"//*.*?/*/", r"/* part1 */ /* part2 */")
print(res)


复制代码

多任务

多任务原理

# -*- coding:utf-8 -*-


''' 什么叫多任务:操做系统能够同时运行多个任务,现代的操做系统好比Windows、Mac OS X、Linux、Unix等都是支持多任务的系统 '''

#单核CPU实现多任务的原理:找图去看



#多核CPU实现多任务的原理:找图

# 为何要实现多任务:想效率高,不卡顿


'''实现多任务的方式 一、多进程模式:启动多个进程,每一个进程虽然只有一个线程,可是多个进程能够一块儿执行多个任务 二、多线程模式:启动一个进程,在一个进程的内部启动多个线程,这样多个线程也能够一块儿执行多个任务 三、多进程+多线程:启动多个进程,每一个进程再启动多个线程 四、协程 五、多进程+协程 '''


复制代码

进程的概念

# -*- coding:utf-8 -*-

''' 什么是进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操做系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体 对于操做系统来讲,一个任务就是一个进程。比方说打开浏览器就是启动一个浏览器的进程,在打开一个记事本就启动一个记事本进程,若是打开两个记事本就启动两个记事本进程。 '''


复制代码

单任务现象

# -*- coding:utf-8 -*-

from time import sleep


def run():
    while True:
        print("sunck is a good man!")
        sleep(1)

if __name__ == "__main__":
    while True:
        print("kaige is a nice man")
        sleep(1.2)
    # 不会执行到run方法,只有上面的while循环结束才行
    run()


复制代码

启动进程实现多任务

# -*- coding:utf-8 -*-



from multiprocessing import Process
from time import sleep

''' multiprocessing模块 一、跨平台的多进程模块 二、提供了一个Process类表明一个进程对象 '''

def run(name, description):
    while True:
        print("%s is a %s man!"%(name, description))
        sleep(1)

if __name__ == "__main__":
    #程序启动的进程称为主进程(父进程)

    #建立进程(子进程)
    p = Process(target=run, args=("sunck", "handsome"))
    #启动子进程
    p.start()

    while True:
        print("kaige is a nice man")
        sleep(1.2)


复制代码

父子进程的前后顺序

# -*- coding:utf-8 -*-

from multiprocessing import Process
from time import sleep

def run():
    print("启动子进程")
    sleep(3)
    print("结束子进程")

def run2():
    print("启动子进程2")
    sleep(3)
    print("结束子进程2")

if __name__ == "__main__":
    print("启动主进程")

    p = Process(target=run)
    p.start()

    p2 = Process(target=run2)
    p2.start()

    #主进程的结束不能影响子进程,随意能够等待子进程结束在结束主进程
    #等待子进程结束,才能继续执行主进程
    #后期主进程主要作的是调度相关的工做,不具体负责业务逻辑
    p.join()
    p2.join()
    print("结束主进程")


复制代码

全局变量在多个进程中不能共享

# -*- coding:utf-8 -*-

from multiprocessing import Process
from time import sleep

money = 10

def run1():
    print("启动子进程1")
    global money
    print("run1---1-", money)  #0
    sleep(3)
    print("run1---2-", money)  #20 真实为0
    money = 30
    print("run1---3-", money)  #30
    print("结束子进程2")

def run2():
    print("启动子进程2")
    global money
    print("run2---1-", money) #0
    sleep(1)
    money = 20
    print("run2---2-", money) #20
    print("结束子进程2")

if __name__ == "__main__":
    print("启动主进程")

    #在建立子进程时会将主进程的资源拷贝到子进程中,子进程单独有一份主进程中的数据。相互不影响
    p1 = Process(target=run1)
    p2 = Process(target=run2)
    p1.start()
    p2.start()

    p1.join()
    p2.join()
    print("money = %d"%money) #30 真实为0
    print("结束主进程")


复制代码

启动大量子进程

# -*- coding:utf-8 -*-
import os
import time
import random

from multiprocessing import Process, Pool

def run(name):
    # os.getpid()获取当前进程的进程ID
    print("子进程%s启动--%s"%(name, os.getpid()))
    t1 = time.time()
    time.sleep(random.random()*5)
    t2 = time.time()
    print("子进程%s结束--%s--耗时%.2f" % (name, os.getpid(), t2-t1))

if __name__ == "__main__":
    print("启动父进程")

    #进程池
    #表示能够同时执行的进程数量
    #因为Pool的默认值为CPU的核心数量,若是有4个核心,则至少须要子进程才能看到等待的效果
    pool = Pool(4)
    for i in range(3):
        # 建立进程放入进程池中赞成管理
        pool.apply_async(run, args=(i,))


    # 进程池对象调用join以前必须先调用close,调用close以后就不能向进程池中添加进程了
    pool.close()
    #Pool对象调用join方法,会等待全部子进程结束在执行主进程
    pool.join()

    print("结束父进程")


复制代码

进程封装

class KaigeProcess(Process):
    def __init__(self, name):
        super().__init__()
        self.name = name
    #当对象调用start方法时,默认调用run方法
    def run(self):
        print("子进程(%s--%s)启动(父进程:%s)"%(self.name, os.getpid(),os.getppid()))
        print("kaige is a good man")
        time.sleep(2)
        print("子进程(%s--%s)结束(父进程:%s)" % (self.name, os.getpid(), os.getppid()))


复制代码

多进程遍历目录

# -*- coding:utf-8 -*-
import os
import time
from multiprocessing import Pool

# path = r"C:\Users\xlg\Desktop\gp01\day14\file"
# filesList = os.listdir(path)
# t1 = time.time()
# for fileName in filesList:
# absPath = os.path.join(path, fileName)
# if os.path.isdir(absPath):
# files = os.listdir(absPath)
# for item in files:
# print(os.path.join(absPath, item))
# t2 = time.time()
# print(t2-t1)


def run(path):
    files = os.listdir(path)
    for item in files:
        print(os.path.join(path, item))
if __name__ == "__main__":
    path = r"C:\Users\xlg\Desktop\gp01\day14\file"
    filesList = os.listdir(path)

    t1 = time.time()
    pool = Pool(5)
    for fileName in filesList:
        absPath = os.path.join(path, fileName)
        pool.apply_async(run, args=(absPath,))
    pool.close()
    pool.join()
    t2 = time.time()
    print(t2 - t1)


复制代码

进程间通讯

# -*- coding:utf-8 -*-

from multiprocessing import Process, Queue
import time
import random

'''进程间通讯 有名管道 无名管道 队列 共享内存 信号 信号量 '''

#
def produce(q):
    print("启动produce子进程……")
    time.sleep(5)
    for value in ["good", "nice", "cool", "handsome"]:
        print("将%s放入队列"%value)
        q.put(value)
        time.sleep(random.random())
    print("结束produce子进程……")

#
def customer(q):
    print("启动customer子进程……")
    while True:
        print("消费者等待数据")
        value = q.get(True)
        print("消费者消费%s条数据"%value)
    print("结束customer子进程……")


if __name__ == "__main__":

    q = Queue()

    pro = Process(target=produce, args=(q,))
    cus = Process(target=customer, args=(q,))
    pro.start()
    cus.start()

    pro.join()
    #cus进程里是死循环,没法等待它的结束,只能强制结束该子进程
    cus.terminate()

    print("END")


复制代码

什么是线程

# -*- coding:utf-8 -*-


''' 线程: 线程,有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程本身不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的所有资源。一个线程能够建立和撤消另外一个线程,同一进程中的多个线程之间能够并发执行。因为线程之间的相互制约,导致线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具有运行的全部条件,逻辑上能够运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每个程序都至少有一个线程,若程序只有一个线程,那就是程序自己。 线程是程序中一个单一的顺序控制流程。进程内有一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行时的程序的调度单位。在单个程序中同时运行多个线程完成不一样的工做,称为多线程 多线程:多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具备多线程能力的计算机因有硬件支持而可以在同一时间执行多于一个线程,进而提高总体处理性能。具备这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理(Chip-level multithreading)或同时多线程(Simultaneous multithreading)处理器。 [1] 在一个程序中,这些独立运行的程序片断叫做“线程”(Thread),利用它编程的概念就叫做“多线程处理(Multithreading)”。具备多线程能力的计算机因有硬件支持而可以在同一时间执行多于一个线程(台湾译做“执行绪”),进而提高总体处理性能 '''


复制代码

启动线程实现多任务

# -*- coding:utf-8 -*-

#模块
''' _thread模块:低级模块 threading模块:高级模块,对_thread进行了封装 '''

import threading
import random
import time

def run1(num):
    print("启动%s子线程1-----%s"%(threading.current_thread().name, num))
    time.sleep(random.random()*5)
    print("结束%s子线程1-----%s" % (threading.current_thread().name, num))

def run2(num):
    print("启动%s子线程2-----%s" % (threading.current_thread().name, num))
    time.sleep(random.random() * 5)
    print("结束%s子线程2-----%s" % (threading.current_thread().name, num))


if __name__ == "__main__":
    # threading.current_thread()获得当前线程对象
    # 主线程的名字默认为MainThread
    print("主线程%s启动……" % threading.current_thread().name)

    #建立线程
    th1 = threading.Thread(target=run1, args=(1,), name="th1")
    th2 = threading.Thread(target=run2, args=(2,), name="th2")

    #启动
    th1.start()
    th2.start()

    #等待子线程结束
    th1.join()
    th2.join()

    print("主线程%s结束……" % threading.current_thread().name)


复制代码

线程间共享数据

# -*- coding:utf-8 -*-

#多线程和多进程最大的不一样在于,多进程中,同一个全局变量,每一个子进程各自有一份拷贝,互不影响。而在多线程中,全部变量都由线程共享,因此任何一个变量均可以被任意线程所修改。所以,多个线程同时改变一个变量,容易把内容改乱了



import threading
import random
import time

money = 0
def changeMoney(n):
    global money
    money = money + n
    money = money - n

def run1(num):
    for i in range(1000000):
        changeMoney(num)

def run2(num):
    for i in range(1000000):
        changeMoney(num)


if __name__ == "__main__":
    #建立线程
    th1 = threading.Thread(target=run1, args=(5,), name="th1")
    th2 = threading.Thread(target=run2, args=(8,), name="th2")

    #启动
    th1.start()
    th2.start()

    #等待子线程结束
    th1.join()
    th2.join()

    print("money = %d"%money)


复制代码

线程锁解决数据混乱

# -*- coding:utf-8 -*-


# 问题:两个线程同时一寸一取,可能形成变量值的不对,咱们必须保证一个线程在修改money的时候,其余的线程必定不能修改


#后期在线程中对变量上锁,可是千万要注意释放锁(本身的锁本身放),不然会形成死锁

import threading
import random
import time

lock = threading.Lock()

money = 0
def changeMoney(n):
    global money
    money = money + n
    money = money - n

def run1(num):
    for i in range(1000000):
        #获取线程锁,若是已上锁,则阻塞等待锁的释放
        lock.acquire()
        try:
            changeMoney(num)
        finally:
            #释放锁
            lock.release()

def run2(num):
    for i in range(1000000):
        with lock:
            changeMoney(num)


if __name__ == "__main__":
    #建立线程
    th1 = threading.Thread(target=run1, args=(5,), name="th1")
    th2 = threading.Thread(target=run2, args=(8,), name="th2")

    #启动
    th1.start()
    th2.start()

    #等待子线程结束
    th1.join()
    th2.join()

    print("money = %d"%money)


复制代码

ThreadLocal

# -*- coding:utf-8 -*-


import threading
import random
import time

# 建立全局ThreadLocal对象
# 每一个线程独立的存储空间
# 每一个Thread对它均可以读写属性操做,可是互不影响
local = threading.local()


def run1(num):
    time.sleep(1)
    local.money = 2
    print("1-------------", local.money,id(local.money))


def run2(num):
    time.sleep(3)
    local.money = 3
    print("3-------------", local.money,id(local.money))



if __name__ == "__main__":
    #建立线程
    th1 = threading.Thread(target=run1, args=(5,), name="th1")
    th2 = threading.Thread(target=run2, args=(8,), name="th2")

    #启动
    th1.start()
    th2.start()

    #等待子线程结束
    th1.join()
    th2.join()

    # print("money = %d"%money)

复制代码

定时线程

# -*- coding:utf-8 -*-

import time
import threading


def run():
    print("sunck is a good man")


if __name__ == "__main__":
    # 常常启动5秒后在执行,不会阻塞主线程
    th = threading.Timer(5, run)

    th.start()

    th.join()

复制代码

线程通讯

# -*- coding:utf-8 -*-

import threading
import time


def func():
    event= threading.Event()
    def run():
        for i in range(10):
            #阻塞
            event.wait()
            #重置
            event.clear()
            print("--------------" + str(i))
    th = threading.Thread(target=run)
    th.start()
    return event

event = func()


for i in range(10):
    event.set()
    time.sleep(1)
print("END")

复制代码

生产者与消费者

# -*- coding:utf-8 -*-


import threading
import queue
import random
import time

def produce(q, index):
    while True:
        num = random.randint(0, 1000000)
        q.put("生产者%s产生数据:%d"%(index, num))
        print("生产者%s产生数据:%d"%(index, num))
        time.sleep(1)
    # 完成任务
    q.task_done()


def customer(q, index):
    while True:
        item = q.get()
        if item is None:
            break
        print("消费者%s获取到:%s"%(index, item))
        time.sleep(4)
    # 完成任务
    q.task_done()


if __name__ == "__main__":
    q = queue.Queue(10)

    arr = []

    #建立三个生产者
    for i in range(3):
        th = threading.Thread(target=produce, args=(q, i))
        th.start()
        arr.append(th)

    # 建立5个消费者
    for j in range(5):
        th = threading.Thread(target=customer, args=(q, j))
        th.start()
        arr.append(th)

    for th in arr:
        th.join()
    print("END")

复制代码

线程调度

# -*- coding:utf-8 -*-

# -*- coding:utf-8 -*-


import threading
import time

#线程条件变量
cond = threading.Condition()

def run1():
    with cond:
        for i in range(0, 10, 2):
            print(threading.current_thread().name+"---"+str(i))
            time.sleep(1)
            cond.wait()
            cond.notify()

def run2():
    with cond:
        for i in range(1, 10, 2):
            print(threading.current_thread().name+"---"+str(i))
            time.sleep(1)
            cond.notify()
            cond.wait()
if __name__ == "__main__":
    th1 = threading.Thread(target=run1, name="th1")
    th2 = threading.Thread(target=run2, name="th2")
    th1.start()
    th2.start()
    th1.join()
    th2.join()

    print("END")

复制代码

进程、线程、协程深度理解

进程可在cpu间切换,线程跟着对应的进程走,协程跟着对应的线程走,线程实际上实现了计算机其余资源(除cpu)的并行使用

复制代码

网络编程

tcp

client

# -*- coding:utf-8 -*-
import socket
import threading

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#元组第一个元素为客户端要链接的服务器的IP地址,第二个参数为服务器的端口号
client.connect(("10.0.122.158", 8080))

# 建立接收线程
def run1(c):
    while True:
        data = c.recv(1024).decode("utf-8")
        print("服务器说:" + data)
th1 = threading.Thread(target=run1, args=(client,))
th1.start()
def run2(c):
    while True:
        # 456#你真坏
        data = input("请输入要发送给服务器的消息:")
        data = "talk#" + data
        c.send(data.encode("utf-8"))
th2 = threading.Thread(target=run2, args=(client,))
th2.start()


client.send("register#123#sunck".encode("utf-8"))


th1.join()
th2.join()
复制代码

server

# -*- coding:utf-8 -*-

import socket
import threading
from person import Person

usersDict = {}

# 一、建立socket
# AF_INET:表示使用IPv4
# SOCK_STREAM:表示TCP协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


#二、绑定
# 参数为一个元组,元组第一个元素为本机ip,第二元素为端口号,使用8000以上的值,最大使用到65535
server.bind(("10.0.122.158", 8080))


#三、监听,设置最多链接数
server.listen(50)



def run(clientSocket, clientAddr):
    while True:
        # register#123#sunck
        # talk#456#sunck nice
        data = clientSocket.recv(1024).decode("utf-8")
        #解析数据
        arr = data.split("#")
        if arr[0] == "register":
            per = Person(clientSocket, arr[1], arr[2])
            usersDict[arr[1]] = per
        elif arr[0] == "talk":
            #找到当前用户的用户名
            name = None
            for account, per in usersDict.items():
                if per.clientSocket is clientSocket:
                    name = per.name
                    break
            #找到好友
            per = usersDict.get(arr[1])
            friendScoket = per.clientSocket
            # 给好友发送消息
            # sunck说:你真帅
            friendScoket.send((name+":"+arr[2]).encode("utf-8"))


#四、等待客户端的连接
while True:
    print("等待连接……")
    #客户端链接成功返回客户端的socket和客户端的IP地址
    clientSocket, clientAddr = server.accept()
    print(clientAddr, "客户连接成功")
    #建立线程交互
    th = threading.Thread(target=run, args=(clientSocket, clientAddr))
    th.start()
复制代码

udp

client

# -*- coding:utf-8 -*-

import socket


client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
    data = input("输入要发送的信息:")
    client.sendto(data.encode("utf-8"), ("10.0.122.158", 8080))





# 如下方式不建议使用
# client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# client.connect(("10.0.122.158", 8081))
# while True:
# data = input("输入要发送的信息:")
# client.send(data.encode("utf-8"))

复制代码

server

# -*- coding:utf-8 -*-


# TCP是创建可靠链接,而且通讯双方均可以以流的形式发送数据。相对TCP,UDP则是面向无链接的协议

# 使用UDP协议时,不须要创建链接,只须要知道对方的IP地址和端口号,就能够直接发送数据包,可是能不能到达就不知道了

# 虽然UDP传输数据不可靠,可是它的优势是和TCP相比较,速度快,对于不要求可靠到达的数据,能够使用UDP,广播类型的软件常用

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(("10.0.122.158", 8081))

while True:
    data, addr = server.recvfrom(1024)
    print("来自", addr, "的消息:", data.decode("utf-8"))

复制代码

使用udp冒充飞秋和轰炸

# -*- coding:utf-8 -*-


import socket

info = "1_lbt4_10#32499#002481627512#0#0#0:1289671407:a:b:288:sunck is a good man"

client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.sendto(info.encode("utf-8"), ("10.0.122.179", 2425))

复制代码
# -*- coding:utf-8 -*-




import socket

info = "1_lbt4_10#32499#002481627512#0#0#0:1289671407:a:b:288:my name is a GP01 gaolei, you neng nai lai zhao wo!"

for i in range(256):
    ip = "10.%d.%d.%d"%(i,i,i)
    print(ip)

复制代码

协程

协程概念

# -*- coding:utf-8 -*-

''' 协程:又称微线程,纤程,是一种用户态的轻量级线程 发展历程: 一、最初的生成器变形yield/send 二、引入@asyncio.coroutine和yield from 三、在最近的python3.5版本中引入了async/await关键字 理解协程: 一、普通理解:线程是系统级别的,他们是由操做系统调度。协程是程序级别的,由程序员根据需求本身调度。咱们把一个线程中的一个个函数称为子程序,那么子程序在执行的过程当中能够中断去执行别的子程序。别的子程序也能够中断回来继续执行以前的子程序,这就是协程。也就是说同一线程下的一段代码1执行执行着就能够中断,而后去执行另外一段代码2,当再次回来执行代码块1的时候,接着从以前中断的地方开始执行 二、专业理解:协程拥有本身的寄存器上下文和栈,协程在调度切换时,将寄存器上下文和栈保存到其余的地方,在切回来时,恢复先前保存的寄存器上下文和栈。所以,协程能保留上一次调用时的状态,每次过程重入时,就至关于进入上一次调用的状态。 子程序:在全部的语言中都是层级调用,好比A中调用B,B在执行过程当中调用C,C执行完返回,B执行完返回,最后是A执行完毕。是经过栈实现的,一个线程就是执行一个子程序,子程序的调用老是有一个入口,一次返回,调用的顺序是明确的 优势: 一、无需线程上下文切换的开销,协程避免了无心义的调度,由此提升了性能,可是,程序员必须本身承担调度的责任,同时协程也失去了标准线程使用多CPU的能力 二、无需原子操做锁定及同步的开销 三、方便切换控制流,简化编程模型 四、高并发+高扩展性+低成本,一个CPU支持上万个协程不是问题 缺点: 一、没法利用多核资源,协程的本质是单个线程,它不能同时将单个CPU的多个核使用上,协程须要和进程配合使用才能运行在多CPU上。可是通常不须要,除非是CPU密集型的应用 二、进行阻塞操做(耗时IO)会阻塞整个程序 '''
# def A():
# def B():
# def C():
# pass
# C()
# B()
# A()


def A():
    print(1)
    print(2)
    print(3)
def B():
    print("a")
    print("b")
    print("c")
''' 协程可能实现其余的打印效果 1 2 a b 3 c '''

复制代码

协程的数据传递

# -*- coding:utf-8 -*-

def func():
    data = "#"
    # yield不但能够返回一个值,而且它还能够接收调用者发送的参数
    r = yield data
    print("-------------1", r, data)
    r = yield data
    print("-------------2", r, data)
    r = yield data
    print("-------------3", r, data)
    r = yield data

g = func()
print(g, type(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
#启动g
print(g.send(None))
print(g.send("a"))
print(g.send("b"))
print(g.send("c"))

复制代码

协程实现生产者消费者

# -*- coding:utf-8 -*-
import time
import threading

def produce(c):
    print(threading.current_thread().name)
    c.send(None)
    for i in range(5):
        print("[produce] 生成数据%d"%i)
        #发送给消费者
        res = c.send(str(i))
        print("[produce] 消费者反馈:%s"%res)
        time.sleep(2)
    #关闭消费者
    c.close()

def customer():
    print(threading.current_thread().name)
    res = ""
    while True:
        data = yield res
        if not data:
            return
        print("[customer] 消费数据%s"%data)
        res = "200 OK"


c = customer()
produce(c)

复制代码

同步与异步

# -*- coding:utf-8 -*-

#前言:python因为GIL(全局锁)的存在,不能发挥多核的优点,其性能一直被人诟病。然而在IO密集型的网络编程里,异步处理比同步处理性能会提高成百上千倍


#同步:只完成事物的逻辑,先执行第一个事物,若是阻塞了,会一直等待,直到这个事物完成,在执行第二个事物,顺序执行


#异步:是和同步相对的,指在处理调用这个事物的以后,不会等待这个事物的处理结果,直接去处理第二个事物了,经过状态、通知、回调来通知调用者处理结果

复制代码

同步代码

# -*- coding:utf-8 -*-
import time

def func():
    time.sleep(1)


for i in range(5):
    func()
    print("time:%s"%time.time())

复制代码

异步代码

# -*- coding:utf-8 -*-
import time
import asyncio

#定义异步函数(定义一个协程)
async def func():
    #模拟一个耗时IO操做
    asyncio.sleep(1)
    print("time:%s"%time.time())

loop = asyncio.get_event_loop()
for i in range(5):
    loop.run_until_complete(func())

复制代码

asyncio模块概述

# -*- coding:utf-8 -*-

''' asyncio模块使python3.4版本引入的标准库,直接内置了对异步IO的支持 编程模式:是有一个消息循环,咱们从asyncio模块中直接获取一个EventLoop的引用,而后把须要执行的协程扔到EventLoop中执行,就实现了异步 说明:到目前为止实现协程的不只只有asyncio,还有gevent和tornado都实现了相似的功能 关键字说明: 一、evnet_loop 事件循环:程序开启一个无限循环,把一些函数注册到事件循环中,当知足条件发生时,调用相应的协程函数 二、coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会当即执行函数,而是会返回一个协程对象。协程对象须要注册到事件循环中,由事件循环调用 三、task 任务:一个协程对象就是一个原生能够挂起的函数,任务则是对协程进一步的封装,其中包含了任务的各类状态 四、future:表明未来执行或没有执行的任务的结果,它和task上没有本质上区别 五、async/await:python3.5用于定义协程的关键字,async定义一个协程,await用于挂起阻塞异步调用接口 '''

复制代码

定义一个协程

# -*- coding:utf-8 -*-

import time
import asyncio

# 经过async关键字定义了一个协程,协程不能直接运行,须要将协程加入到事件循环中
async def run(x):
    print("waiting:%d"%x)

start = time.time()

# 获得一个协程对象,这个时候run()函数没有执行
coroutine = run(2)
# print(coroutine)

# 建立一个事件循环(注意:真实状况是在asyncio模块中获取一个引用)
loop = asyncio.get_event_loop()
# 将协程对象加入到事件循环
loop.run_until_complete(coroutine)

end = time.time()
print("Time:", end - start)

复制代码

建立一个task

# -*- coding:utf-8 -*-

import time
import asyncio

async def run(x):
    print("waiting:%d"%x)

start = time.time()





coroutine = run(2)

loop = asyncio.get_event_loop()
# 将协程对象加入到事件循环,协程对象不能直接运行,在注册事件循环的时候,实际上是run_until_complete方法将协程对象包装成了一个任务对象,task对象是Future类的子类,保存了协程运行后的状态,用于将来获取协程的结果
# loop.run_until_complete(coroutine)

#建立任务
task = asyncio.ensure_future(coroutine)
# task = loop.create_task(coroutine)
print(task)
#将任务加入到事件循环
loop.run_until_complete(task)
print(task)



end = time.time()
print("Time:", end - start)

复制代码

绑定回调

# -*- coding:utf-8 -*-

import time
import asyncio

async def run(x):
    print("waiting:%d"%x)
    return "done after %ds"%x

#定义一个回调函数,参数为future,任务对象
def callback(future):
    print("callback:", future.result())

start = time.time()





coroutine = run(2)
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(coroutine)
#给任务添加回调,在任务结束后调用回调函数
task.add_done_callback(callback)
loop.run_until_complete(task)



end = time.time()
print("Time:", end - start)

复制代码

阻塞和await

# -*- coding:utf-8 -*-

import time
import asyncio

#async能够定义协程对象,使用await能够针对耗时的操做进行挂起,就行生成器里的yield同样,函数交出控制权。协程遇到await,事件循环将会挂起该协程,执行别的协程,直到其余协程也挂起或者执行完毕,再进行下一个协程的执行
async def run(x):
    print("waiting:%d" % x)
    # 调用了一个耗时IO操做
    # asyncio.sleep(x)另外一个协程对象
    await asyncio.sleep(x)
    return "done after %ds" % x
def callback(future):
    print("callback:", future.result())

start = time.time()

coroutine = run(2)
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(coroutine)
task.add_done_callback(callback)
loop.run_until_complete(task)



end = time.time()
print("Time:", end - start)

复制代码

并发和并行

# -*- coding:utf-8 -*-

''' 并发:指有多个任务须要同时进行 并行:同一时刻有多个任务执行 并发相似一个老师在同一时间段辅导不一样的人功课,并行好几个老师分别同时辅导多个学生。 '''

import time
import asyncio

async def run(x):
    print("waiting:%d" % x)
    # 调用了一个耗时IO操做
    # asyncio.sleep(x)另外一个协程对象
    await asyncio.sleep(x)
    return "done after %ds" % x

start = time.time()

coroutine1 = run(2)
coroutine2 = run(3)
coroutine3 = run(4)
coroutine4 = run(5)

tasks = [
    asyncio.ensure_future(coroutine1),
    asyncio.ensure_future(coroutine2),
    asyncio.ensure_future(coroutine3),
    asyncio.ensure_future(coroutine4)
]


loop = asyncio.get_event_loop()
#一、添加任务列表
# loop.run_until_complete(asyncio.wait(tasks))
#二、
loop.run_until_complete(asyncio.gather(*tasks))

for task in tasks:
    print("Task 返回值:", task.result())



end = time.time()
print("Time:", end - start)

复制代码

协程嵌套

# -*- coding:utf-8 -*-


import time
import asyncio

async def run(x):
    print("waiting:%d" % x)
    await asyncio.sleep(x)
    return "done after %ds" % x

start = time.time()


async def main():
    coroutine1 = run(2)
    coroutine2 = run(3)
    coroutine3 = run(4)
    coroutine4 = run(5)
    tasks = [
        asyncio.ensure_future(coroutine1),
        asyncio.ensure_future(coroutine2),
        asyncio.ensure_future(coroutine3),
        asyncio.ensure_future(coroutine4)
    ]
    #一、
    # dones, pendings = await asyncio.wait(tasks)
    # for task in dones:
    # print("Task 返回值:", task.result())

    #二、
    # results = await asyncio.gather(*tasks)
    # for result in results:
    # print("task 返回值:", result)


    #三、
    # return await asyncio.wait(tasks)

    #四、
    # return await asyncio.gather(*tasks)

    #五、
    for task in asyncio.as_completed(tasks):
        result = await task
        print("task返回值:", result)

loop = asyncio.get_event_loop()
#一、
# loop.run_until_complete(main())
#二、
# loop.run_until_complete(main())
#三、
# dones, pending = loop.run_until_complete(main())
# for task in dones:
# print("task返回值",task.result())
#四、
# results = loop.run_until_complete(main())
# for result in results:
# print("task 返回值:", result)
#一、
loop.run_until_complete(main())


end = time.time()
print("Time:", end - start)

复制代码

不一样线程的事件循环

# -*- coding:utf-8 -*-

#通常状况咱们的事件循环用于注册协程,有一些协程须要动态的添加到事件循环中。简单的方式就是使用多线程,当前线程建立一个事件循环,而后开启一个新线程,在新线程中启动事件循环,当前线程不会被block


import asyncio
import time
import threading

def start_loop(lp):
    #启动事件循环
    asyncio.set_event_loop(lp)
    lp.run_forever()

def run(x):
    print("waiting:%d" % x)
    time.sleep(x)
    print("finish after %ds" % x)

start = time.time()


loop = asyncio.get_event_loop()


#建立新线程,用于启动事件循环,此时不会阻塞主线程了
threading.Thread(target=start_loop, args=(loop,)).start()

end = time.time()
print("time:", end-start)

#给事件循环添加任务
loop.call_soon_threadsafe(run, 4)
loop.call_soon_threadsafe(run, 6)

复制代码

新线程协程

# -*- coding:utf-8 -*-

#通常状况咱们的事件循环用于注册协程,有一些协程须要动态的添加到事件循环中。简单的方式就是使用多线程,当前线程建立一个事件循环,而后开启一个新线程,在新线程中启动事件循环,当前线程不会被block


import asyncio
import time
import threading

def start_loop(lp):
    #启动事件循环
    asyncio.set_event_loop(lp)
    lp.run_forever()

async def run(x):
    print("waiting:%d" % x)
    await asyncio.sleep(x)
    print("finish after %ds" % x)

start = time.time()


loop = asyncio.get_event_loop()


#建立新线程,用于启动事件循环,此时不会阻塞主线程了
threading.Thread(target=start_loop, args=(loop,)).start()

end = time.time()
print("time:", end-start)

#给事件循环添加任务
asyncio.run_coroutine_threadsafe(run(4), loop)
asyncio.run_coroutine_threadsafe(run(6), loop)

复制代码

获取网页信息

# -*- coding:utf-8 -*-

# www.163.com www.baidu.com www.sohu.com www.sina.com.cn www.google.com
# 3 5 2 6

import asyncio
import time
import threading


def start_loop(lp):
    asyncio.set_event_loop(lp)
    lp.run_forever()

async def wget(urlStr):
    print("开始加载%s……"%urlStr)
    connet = asyncio.open_connection(urlStr, 80)
    print("***********************",connet)
    reader, writer = await connet
    #连接成功
    header = "GET / HTTP/1.0\r\nHost: %s\r\n\r\n"%urlStr
    writer.write(header.encode("utf-8"))
    await writer.drain()
    #接收到数据
    while True:
        line = await reader.readline()
        if line == b'\r\n':
            break
        print("%s header--->%s"%(urlStr, line.decode("utf-8").strip()))
    writer.close()


loop = asyncio.get_event_loop()
threading.Thread(target=start_loop, args=(loop,)).start()


#给时间循环添加任务
for url in ["www.163.com","www.sohu.com","www.sina.com.cn","www.baidu.com"]:
    asyncio.run_coroutine_threadsafe(wget(url), loop)
复制代码

json数据的序列化和反序列化

# 序列化:将Python对象转换成json字符串
dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

# 反序列化:将json字符串转换成Python对象
loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

# 序列化:将Python对象转换成json字符串并存储到文件中
dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

# 反序列化:读取指定文件中的json字符串并转换成Python对象
load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

参数说明:
	sort_keys参数: 表示序列化时是否对dict的key进行排序(dict默认是无序的)
	
	indent参数: 表示缩进的意思,它能够使得数据存储的格式变得更加优雅、可读性更强;如	果indent是一个非负整数或字符串,则JSON array元素和object成员将会被以相应的缩进级	   别进行打印输出;若是indent是0或负数或空字符串,则将只会插入换行,不会有缩进。
    
    separators参数: 尽管indent参数能够使得数据存储的格式变得更加优雅、可读性更强,但	是那是经过添加一些冗余的空白字符进行填充的。当json被用于网络数据通讯时,应该尽量	  的减小无用的数据传输,这样能够节省带宽并加快数据传输速度。json模块序列化Python对	    象后获得的json字符串中的','号和':'号分隔符后默认都会附加一个空白字符,咱们能够经过	 separators参数从新指定分隔符,从而去除无用的空白字符;

    该参数的值应该是一个tuple(item_separator, key_separator)
    若是indent是None,其默认值为(', ', ': ')
    若是indent不为None,则默认值为(',', ': ')
    咱们能够经过为separator赋值为(',', ':')来消除空白字符
    
    ensure_ascii参数: 当该参数的值为True(默认值)时,输出中的全部非ASCII字符(好比	   中文)都会被转义成'\uXXXX'组成的序列,获得的结果是一个彻底由ASCII字符组成的str实	   例。若是咱们想获得一我的类可读的输出结果,须要把ensure_ascii参数的值设置为			False。
复制代码

chardet

# -*- coding:utf-8 -*-



#做用:使用chardet检测编码,支持检测中文、日文、韩文等多种语言

# pip install chardet

import chardet

#数据量小,猜想的不太对
data = "凯".encode("gbk")
print(data)

s = chardet.detect(data)
print(s)
print(type(s))

info = data.decode(s["encoding"])
print(info)

复制代码

python2和python3的区别

# -*- coding:utf-8 -*-

# 一、性能
#python3.x起始比python2.x效率要低,可是python3.x有极大的优化空间,效率正在追赶,目前已经不差多少。


# 二、编码
#python3.x原码文件默认使用utf-8,使变量名更为广阔


# 三、语法
# 3.一、去除了<>,改用!=
'''3.二、 / python2.x整型触发返回整数 python3.x整型触发返回浮点数,整除使用// '''
# 3.三、加入了nonlocal语句
# 3.四、去除了print语句,加入了print()函数
# print("sunck", end=" ")
# print("kaige")
# 3.五、去除了raw_input语句,加入了input()函数
# 3.六、新的super(),能够再也不给super()传递参数
# class A(object):
# pass
# class B(A):
# def __init__(self):
# super().__int__()
# 3.七、改变了顺序操做符的行为,好比x<y,当x和y类型不匹配时抛出TypeError异常
# 3.八、新式的8进制数字变量



# 四、字符串和字节串
''' python2.x 字符串以8bit字符串存储 python3.x 字符串以16bit Unicode字符串存储,如今字符串只有str一种类型 '''




# 五、数据类型
#python3.x去除了long类型,如今只有一种整数类型int,可是它的行为就像2.x中long
#新增了bytes类型,对应2.x版的八位串







# 六、面向对象
# 引入抽象基类




# 七、异常
#全部异常都从BaseException继承,并删除了StardardError
''' python2 try: …… except Exception e: …… python3 try: …… except Exception as e: …… '''





# 八、其余
# python2.x中的xrange()在python3.x中名为range()
''' file类被废弃 python2能够使用file(path)、open(path) '''
复制代码

PEP8编码规范

# -*- coding:utf-8 -*-
#英文教程:https://legacy.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds

#中文教程:https://blog.csdn.net/ratsniper/article/details/78954852



''' 代码编排 一、缩进4个空格,禁止空格与Tab混用 二、行长79,防止单行的逻辑过于复杂 '''
if 1:
    pass



''' 命名 一、除非在lamdba函数中,不然不要使用单字母的变量名,可是即便在lamdba函数中变量名也要尽量有意义 二、包名、模块名、函数名所有使用小写,单词使用下划线连接 三、类名、异常名使用首字母大写的方法,异常名结尾加Error或者Warning 四、全局变量尽可能使用大写,同一类型的全局变量要加同一的前缀,单词用下划线连接 五、自定义的变量、函数名等不要与标准库名冲突 六、函数名必须有动词,最好是do_something的句式或者somebody_do_something句式 '''
COLOR_RED = 10
COLOR_BLUE = 11
f = lambda x: x+1
def func(x, y):
    pass
def get_money():
    pass





''' 注释 一、忌讳没有注释和逐行注释 二、行内注释 当行逻辑过于复杂添加 三、块注释 一段逻辑开始时注释 四、引入外来算法或者配置时必须在注释中添加源连接,标明出处 五、函数和类尽可能添加docstring '''
def do_eat(x, y):
    print("------------")




''' 空格 一、:,;后面要跟一个空格,前面没有空格,行尾分号无需空格 二、二元操做符先后各一个空格 数学运算符、比较运算符、逻辑运算符、位运算符 三、=的注意事项:用于指示关键字参数或默认参数值时,不要添加空格 '''
a = 1
def f(x, y=1):
    pass


''' 换行 一、适当添加换行 二、函数间 一、顶级函数空间空2行 二、类的方法空1行 三、文件结尾留空一行 '''



''' import 一、不要使用from xxx import * 二、导入顺序(标准库、第三方、自定义) a、标准库 b、第三方库 c、自定义库 三、单行不要导入多个库 四、模块内用不到的不要去import '''



''' 字符串拼接 一、拼接方法 a、字符串相加 (性能最差) b、字符串格式化 c、python3.6支持f操做符 >>> a = 111 >>> b=222 >>> c=333 >>> s = f"{a}-{b}-{c}" >>> s '111-222-333' d、join 二、尽可能使用join方法,由于速度快,内存消耗小 '''




''' 语义 一、要求明确、直白 not x in y x not in y not x is y x is not y '''


''' 测试工具: pep8:即将失效,用pycodestyle替换 pylint:更加严格,引入的包没有使用均可以检测出来 flake8: '''
复制代码
相关文章
相关标签/搜索