循环
if
elif
else
%f 占位浮点型,默认6位,指定保留几位小数则用用 %.nf,默认四舍五入。
字符串
字符串查找可以用 index() ,也可以用 find()
find 如果找不到则会返回-1, index 如果找不到则会导致崩溃。
统计某个字符串长度用len()
统计某个字符在字符串中出现的次数, xx.count("?")
替换replace,
分割 split ,分割后放到一个列表里。
判断是否以指定数据开头 .startwith('xxx')
endwith('xxx')
以指定字符将字符串分割为几部分
xx.partation('b') 返回一个元组
xx.join('-') 以指定字符拼接字符串的字符
join 也可以拼接元组
去除空格
xx.strip()
xx.lstrip() 去除左侧空格
xx.rstrip() 去除右侧空格
列表与元组
列表
列表里可以包含多种类型
列表有正负下标,正下标从0开始, 负下标从-1开始
空列表
my_list = []
添加内容 my_list.append(1)
插入数据my_list.insert(index, value)
将一个列表以内容形式增加到原有列表用extend()
根据下标删除内容my_list.pop() 默认删除最后一个
根据下标删除del my_list[index] ,如果index 超出索引范围会报错
根据内容删除my_list.remove(value)
my_list.pop(index) 删除指定位置的内容
通过下标修改指定数据
确定内容是否存在于列表中
value in list
my_list.index(value) 要注意,如果value 不在的话则会崩溃。
my_list.count(value) 返回出现次数。
元组
元组也可以放多种类型
元组不可以增删改
可以通过下标取值
应用方法与列表类似
字典和列表 都可以用del 进行删除
字典与集合
字典
字典取值两种方法 my_dic[key], my_dic.get(key) ,1中的key不存在则崩溃,2 则不会。
key 不在字典里则为添加,在的话则为修改。
字典删除是 popitem() 从一个字典中要删除的项目 ,随机删除键值对
my_dic.pop(key) 删除一个key的item 并返回value
集合
my_set.remove(), remove 根据key删除数据,如果不存在则会报错
my_set.discard(),discard根据key删除数据,如果不存在则忽略报错。
my_set不支持以下标形式删除。
集合是无重复的,可以对容器类型数据去重。
循环
while
for
都可以后面跟else
遍历集合元素取下标 用enumerate(容器)
拆包
定义:通俗讲 把容器类型中的每一个数据使用不同变量进行保存
变量个数 要跟容器中元素个数要一致, 不一致会出我问题
n1 , n2 = num[1,2]
函数
参数
形参, 在函数定义的地方称为形参
实参,在函数被调用的地方称为实参
局部变量,在函数内部定义使用,
全局变量,在函数外部定义使用
如果定义了全局变量,在函数内又有同名字的变量,则为新定义的局部变量,而不是全局变量,要把局部变量转换为全局变量,则在局部变量前面加上global。
传参方式
位置参数,关键字参数
位置参数必须在关键字参数之前
关键字参数与传入位置无关
强制位置参数以关键字参数进行传递则在位置参数前面加一个*,
def demo(*, n1, n2) 这样定义之后 n1 和n2就必须以关键字参数进行传递了。
函数被调用的时候可以以关键字参数进行传入,也可以再保证类型的前提下以位置参数进行传递。
位置参数和关键字参数只在函数被调用时候才被区分
必选参数&&可选参数
必选参数必须放到可选参数前面, 可选参数是关键字参数的一种形式,
可选参数可以传入也可以不传入,不传入就用默认值,如果传入则会覆盖默认值,用传入的值。
不定长参数
不定长位置参数&&不定长关键字参数
不定长位置参数通常用*args
不定长关键字参数通常用**kwargs
不定长位置参数 类型是 tumple
不定长关键字参数类型是 字典
如果要将字典以不定长关键字传入则用**进行拆包
如果要将元组以不定长位置参数传入则用*进行拆包
匿名函数
lambda, 简化函数,调用简单,只被调用一次
例如: result = (lambda x ,y : x+y)
冒号前x,y 是参数, 冒号后是返回值
匿名函数可以进行判断 result = (lambda n : True if n %2 == 0 else False)
嵌套函数
即在函数内部定义的函数为嵌套函数
嵌套函数只能在被嵌套的函数里面调用。
递归函数
自己调用自己的函数为递归函数
递归函数必须有传递,有回归,即有终结条件,不能陷入死循环。
例如:
5! = 5 *4!
4! = 4*3!
3! = 3 * 2!
2! = 2*1!
1 = 1
def calc_num(n):
if n == 1:
return n
else:
return n*calc_num(n-1)
传入3,会走else ,会调用2阶乘,又走else 调用1的阶乘,这次返回1 给2的阶乘计算完结果后返回给3的阶乘作为最终返回。
列表生成式
通常用for循环 生成一个列表 for i in range(0,10)
列表生成式 my_list = [val for val in range(0,10)]
列表生成式里面可以进行计算, for循环, 嵌套, if判断
引用
通俗将 程序中的数据在内存中的地址。
查看内存地址 用 id()
转成16进制 hex(id())
可变类型 和不可变类型
可变类型是在原来基础上进行更变数据,修改后内存地址不变
不可变类型,不能在原有基础上修改,直接赋值新值后内存地址发生改变
可变类型:列表, 字典,集合, 修改数据后内存地址不发生改变。
不可变类型:字符串,数值, 元组,不能再原内存地址上修改数据。
global
global 是用来将 不可变类型变量变成 全局变量,内存地址发生变化
可变类型 可以不加global 就可以在函数内引用全局变量, 地址不发生变化,如果加上global 则会地址发生变化。
不加global 数据会发生变化,但是内存地址不变, 加上global 内存地址会发生变化。
公共运算符 + *
+ 可以完成字符串,列表,元组拼接
* 可以完成字符串,列表,元组的复制。
元组、集合、列表可以相互转化
tumple() ,set() ,list()
函数文档
在函数内部用 三个引号引起来的内容
偏函数
函数偏爱某个值的函数 则为偏函数
def show(n1,n2,n3 = 1):
pass
def show2(n1,n2,n3 = 2):
pass
show2则为偏函数
这样定义有点麻烦,怎么简便些
#引入包 functools
import functools
def show(n1,n2,n3 = 1):
pass
new_func = functools.partial(show, n2 = 3)
result = new_func(2)
print(result)
new_func 则为一个偏函数
返回函数
返回值是一个函数的函数
作用,根据条件,返回不同处理功能的函数,例如通过运算符分别返回不同的运算函数。
返回函数也是一种高阶函数
高阶函数
参数可以接收一个函数,也可以返回一个函数,则是高阶函数
接收 返回是或的关系,满足其一都是高阶函数
闭包
在函数嵌套的情况下,内部函数使用了使用了外部函数的参数或者变量,并把这个内部函数进行了返回,返回的内部函数则称为闭包(闭包其实就是一个函数)
图中的inner 则就是闭包
闭包的好处是根据条件生成不同的函数 ,这里跟返回函数的功能有类似。
但是返回函数实现根据不同条件返回不同函数是需要在返回函数的母函数里提前把函数定义好,他可以进行不同逻辑的处理函数。
闭包分局不同条件返回的函数,只需要定义好逻辑,返回不同内存地址的不同函数,返回的函数逻辑处理是一样的,只是处理的实际数据不同而已。
装饰器
本质上就是一个函数,可以给原函数的功能进行扩展
好处是 不改变原函数的定义和调用
装饰器 是闭包的一种体现
不改变原函数的调用 其实是相同名字的函数,但是内容已经是装饰器返回的一个函数。
装饰一个带有参数的函数,则在定义装饰器的时候,装饰器的返回函数也同样要带有相同的参数。
如果原函数有返回值,装饰器的内部函数也要有返回值。
总之,原函数有啥,返回啥,装饰器的返回函数就要有啥,返回啥!
根据不同条件返回不同的装饰器,比如打印10个*,另外一个人想打印10个+,那在定时装饰器的外面在定义一个函数,这个外函数接受一个参数,装饰器引用外函数的参数,外函数返回装饰器(此时装饰器是一个闭包:因为他引用了外函数的参数并且返回了装饰器)。
def dec_decrator(char):
def decorator(func):
def inner():
print(char * 10)
func()
return inner
return decorator
#@后面调用的函数返回一个装饰器,装饰器里又返回一个函数
@dec_decrator('*') show ==> decorator(show) = dec_decrator(‘*’)
def show():
print('it is show')
show()
装饰器要满足不同参数个数的函数,这个装饰器要有通用性,则装饰器内部的返回函数要接受一些不定长参数
def decrator (func):
def inner(*args, **kwargs):
print('i am inner')
func(*args, **kwargs)
return inner
一个函数可以用多个装饰器,最上面的装饰器会将他下面的内容作为一个函数进行装饰。
文件操作
# r 模式
file = open('1.txt',r)
file.read()
file.close()
指定文件打开的编码格式 encoding= 'utf-8'
a 模式是追加,
rb 二进制读取不需要指定编码格式
读取数据的时候需要解码 decode('utf-8')
wb 二进制清空再写数据
需要编码encode('utf-8')
ab 二进制追加数据
r+ 有写的功能,但是必须先看主模式, 主模式是读,所以需要文件先存在,不存在就会报错。
read是根据不同模式 读1位,如果是r, 是数据长度, 如果是rb是 读取字节数
文件指针位置
readline按行读取数据,会带有换行符
readlines 是把全部数据按行读出来,是一个集合。
最常用的模式是 rb 和wb模式
模拟大文件拷贝,按字节个数拷贝,直到读取到字节数为0
路径操作
import os
删除文件os.remove(xxxx)
删除空目录os.rmdir(path)
删除有文件的文件夹需要引入shutil,用 shutil.rmtree(xxx)
import shutil
定义类
旧式类
新式类 类定义的时候继承 object 。
对象创建的时候,定义好属性。在init里定义好。self表示实例后的当前对象。
__str__
返回对象的字符串描述
__del__
1 当程序退出时, 2 当对象被删除时,并且没有对象引用类时候, 则调用该魔法方法
继承
子类复用 父类的方法。
单继承,多继承
多继承中 根据类继承顺序 找对应的方法,先继承的父类,会被先查找
super
__init__里使用 super
如果子类有 init方法,则继承的父类中的init则不会被调用。
如果子类中有同父类一样的方法名,在子类的init 方法中调用init方法,是绝对不能用self.init的,首先不会调用父类的方法,第二,会发生递归。
在属性或方法前面加上__变成私有
在对象外是不能访问的。
对象名.__dict__查看对象属性, 私有属性被伪装成了对象名+私有属性名的拼接。
类名.__dict__查看类方法,私有方法被伪装成了类名+私有方法名的拼接。
类属性和对象属性
实例可以访问类属性,但是类不能访问实例属性
对象不能修改类属性,如果名字相同只是新增了一个类属性,而非修改
总结类属性由类操作,实例属性由实例操作,
类方法和静态方法
类方法@classmethod, 方法参数里传入(cls)
类方法可以修改类属性,例如类私有参数,通过定义的类方法修改私有属性
静态方法:与类和对象都无关的方法
多态
关注同一个方法,但是有不同的表现形式,其他语言的多态是在一个类里面定义同名称的方法,而python里则是 在不同类里定义同名方法以实现(伪)多态
魔法方法new
魔法方法new是在创建对象的时候调用
创建对象先调用new 方法,在调用init 方法将对象进行初始化
new里的参数需要兼容init 里面的参数的,new虽然不用,但是必须要有。
用new 方法实现单例
单例:不管创建多少个对象,只有一个实例(一个内存地址)
slots 将一个元组赋值给__slots__ 就可以将实例参数进行固定,不允许再添加。
property把方法名改成属性
在程序中有set 方法和 get 方法,
先定义get 方法加上@property装饰器即可把get 方法变成get 属性了。
例如:
socre = 100
@property
def get_score (self):
return self.score
@get_score.setter
def set_score (self, socre):
self.score = socre
没有加property时候调用的时候是 xxx.get_score()
加上property之后 则可以用等号去设置值 xxx.get_socre
同样setter方法上面加上对应的get方法.setter与get方法形成配对
没有配对get方法时候调用的时候是 xxx.set_score(90)
配对get之后 则可以用等号去设置值 xxx.set_socre = 90
必须先把get 方法放到set 方法的前面
异常捕获
try
except Exception as e:
捕获异常可以用元组写到一起,也可以单独并且分开写,没有异常就会走到else里面,有没有异常都会走到finally里。
自定义异常, 要继承Exception 类
raise 只能抛出异常类型。
模块
模块就可以认为是一个py文件就是一个模块
一个py文件调用另外一个模块的时候,会先执行被调用模块的代码,防止一些信息不是执行py文件要的内容,在被调用的模块里,要把只与自己相关的内容加在判断是否为主模块之内。 if__name__ == '__main__':
引用模块方式
import module
from module import xxx 导入功能代码
from module import * 导入所有,
在被调用的模块里定义一个 列表赋值给魔法变量all ,则会限定本模块被导入的内容。
导入模块时候 可以给模块起别名,也可以给功能代码起别名。
包
包含魔法init文件管理多个模块的文件夹为包
from package import * , 默认不会导入包里的所有模块,需要在包的init文件里 定义个 列表赋值给 all的魔法变量
不能直接导入包里的模块,会报错, 如果要导入的话,必须在包的init文件里将模块进行导入,这样外面才能使用。
在包的init 文件中为了省略包名称 可以用 . (本包)代替, 点代表本包。
stringIO , 在内存中操作数据
StringIO与文件读写很类似
要导入io包
在io里, StringIO 不能 写入二进制数据,如果要写入二进制数据则需要在io 里再导入BytesIO
用BytesIO写入二进制数据的时候 ,要进行编码
用getValue()读取全部数据
读数据的时候 要进行解码。
序列化
反序列化
序列化和反序列化都是以二进制方式进行的
序列化不仅可以对集合类型序列化而且也可以将对象进行序列化
用json进行序列化和反序列化, 也是需要用二进制方式进行序列化
json 只适合部分类型,不通用, 比如列表,字典 ,int 类型,自定义类型不支持。
可迭代对象: 元组, 列表, 字典, 字符串,集合, range()
用for 循环遍历取值的对象,就是可迭代对象,
isinstance(value , 类型), 判断是不是指定类型。
dir(val) 获取 val的属性信息
迭代器
在类里面有 魔法方法 iter, next 创建的对象就是迭代器,
作用是根据数据的位置获取下一个位置
生成器
生成器与 列表表达式很类似, 就是将 列表生成器的[ ], 换成()就可以变成生成器。
yield创建生成器, 与return不同是,return只返回一次,而yield 会多次返回,并从上次返回的指针处返回。
** 生成器只能往后面取, 不能往前面取
生成器和迭代器的好处是 可以节省内存**
线程和进程
线程
需要导入 threading
执行代码的分支就是线程,默认只有一个分支。
启动线程有两种方式,1种是创建少于任务总数的子线程,一个任务用主线程跑,第二种是有几个任务,创建几个线程,创建完线程后要进行启动,例如sub_thred.start()
用args接收 元组的类型的 参数, 用kwargs 接收字典类型的参数
主线程会等待所有的子线程结束后再结束
想要主线程执行结束后,子线程就要结束,就要设置守护线程,
方法1 是创建完子线程后 用set方法进行再次设定,
方法2 是在创建的时候,通过类似于,target ,args 一样,通过daemon 属性进行设定。
方法二, t1 = threading.Thred(target = AA , deamon = True)
线程可以共享资源,但是会发生资源竞争, 为了避免资源竞争,通过互斥锁可以解决。
互斥锁
创建互斥锁
lock = threading.Lock()
创建完互斥锁后,在不同的线程方法内进行上锁和 解锁
上锁
lock.acquire()
逻辑部分
逻辑部分执行后要进行解锁
lock.release()
进程
创建子进程与创建子线程方法类似
创建完之后也需要启动。
主进程 也会等待子进程执行结束后结束。
有两种方法控制主进程结束后子进程也跟着结束
1 设置进程为守护进程
sub_process.deamon = True
- 手动终止 子进程
sub_process.terminate()
如果想要一个进程执行之后在进行下一个进程 则用 第一个进程的join方法
例如
sub1_process.start()
sub1_process.join() 等待sub1_process执行完之后在进行下面代码
sub2_process.start()
上面代码是启动了子进程1 ,然后等待执行完进程1 之后再启动进程2。
put 存数据, get 取数据
子进程间不共享资源, 相互独立。
用消息队列进行解决
在 创建进程前先创建消息队列,
将消息队列以参数形式传递到进程里
在读取的进程中要判断队列是否为空,空的时候跳出。
写队列用put, 读队列用get