likes
comments
collection
share

一个前端转python速通学习之路(长篇)

作者站长头像
站长
· 阅读数 11

由于公司python离职,必须兼顾python项目的维护,于是恶补了python,写出一份速通攻略,以提供前端想学习python的朋友,此文字默认跳过安装pycharm和python环境,不对的地方欢迎指出

基础篇

一、数据类型

六种:

数字(Number)整数(int)浮点数(float) 复数(complex)布尔(bool)复数:4+3j布尔:底层true是1 ,false是0定义布尔首字母要大写 True
字符串(String)
列表(List)有序可变序列 (数组)
元组(Tuple)有序不可变序列(元组)
集合(Set)无序不可重复
字典(Dictionary)无序key-value集合

1.1. 查看数据类型

  • type()
name = "张三"
print(type(name))
# <class str>

1.2. 类型转换 str() int() float()

  • 转字符串 str()

任何类型都可以转字符串

str=(11)

  • 转整数-数字 int()

需要确保字符串内容全是数字

浮点转整数-去除小数部分

  • 转浮点数-数字 float()

整数浮点 补充.0 如11 =>11.0

1.3. 定义数据类型

使用:定义数据类型 或者 用注释#type:

var_1:int=10  #使用:定义 同于ts
var_2=10 # type:int

二.运算符

1.算数运算符

  • // 取整除
  • % 取余数
  • ** 求平方

2.赋值运算符

-+ 、-=、 *=、 /=、 %= 、**= 、//=

三.变量

1.1. 命名规范

  1. 大小写敏感,如变量可以作为两个变量 如:a 和 A
  2. 不能用关键字 如:False True None And... 必须要大小写一样

1.2. 函数内部 定义全局变量 global

def getName(){
    global name="张三"
}
#需要修改外部的全局变量  需要再函数内部 用global

四、字符串

1.字符串

可以单引号、双引号、三引号(注释)

引号嵌套:字符串要包含引号可以使用\转义

a='123'

b="123"

c='''
	123
	123
'''

2.字符串拼接

  • 方法一:+进行拼接
  • 方法二:%s %变量,如果单个占位 列:“我的名字叫%s”%name,如过多个占位,保持顺序,用括号:“我的名字叫%s,我的年龄%s岁”%(name,age)
  • 方法三:字符串前面f 变量用{},类似模板语法 例如: f"我是{name},我今年{age}"

占位符详解:

%s将内容转换为字符串,放入占位位置
%d将内容转换为整数,放入占位位置,
%5d表示将整数的宽度控制在5位,如果不足用空格补充,如果限制数字位数小于原数字 那么不会生效
%f将内容转换为浮点型,放入占位位置
%5.2d表示将整数的宽度控制在5位,小数精度为2,如果不足用空格补充
%.2d只限制小数

format

#方式1
"{} {}".format("hello", "world")
'hello world'
#方式2
"{1} {0} {1}".format("hello", "world")
'world hello world'

五、字符串方法

1.字符串原字符串无法修改 只能得到新字符串

2.str.index(元素) 查找元素下标

name="张山李四"
name.index("李四")#2  
#返回:命中的第一个下标 没有命中报错

3.str.replace(被替换元素,新元素,最大替换次数) 替换

name="张山李四"
#最大替换次数,如不设置 则全部替换
str=name.replace("张三","李四")
#返回:李四李四

4.str.split(元素) 切分 等同js

name="张山和李四"
arr=name.split("和")
#解析:以 和 切割数组
#返回:[张三,李四]

5.str.strip() 去除空格或者指定元素 rstrip()去掉右边 ltrip()去掉左边

name="  张山和李四  "
#不传入参数
name.strip() #去除首位空格
#返回:"张山和李四"


#传入参数 去除两边字符  没办法除去中间
str="12ASSDF21"
str.strip("12")
#解析:不按照参数顺序 12或者21都要去除
#返回"ASSDF"

6.str.count() 统计某元素出现的次数

name=" 张山和李四和 "
name.count("和") #2

7.len() 统计字符串长度

name=" 张山和李四和"
len(name) #6

8.find() 查找字符串是否出现

str='123'
str.find("4") #-1
#是-返回第一次出现的下标  不是-返回-1

9.caitalize() 首字母大写

str='hello'
str.caitalize() #Hello

10.isdigit() 是否只包含纯数字字符

num="123"
num.isdigit()#true

11.islower() 是否全部包含小写字符

s="heelo"
s.islower()#true

12.lower() 全部变成小写 upper()全部变成大写

s="Hello"
s.lower()#hello
s.upper()#HELLO

13.startwith() 是否以某个字符开头 endwith()是否以指定字符结尾

s="hello"
s.startwith("h")#true
s.endwith("o")#true

14.* 重复生成多个

a="b"
print(a*3)#bbb

六、range

1.一个参数 rang(num)

rang(10)

表示[0,1,2,xxxx,9]

2.两个参数 rang(num1,num2)

rang**(5,10)

表示[5,6,7,8,9] 包头不包尾

3.三个参数 rang(num1,num2,step)

rang(5,10,2)

第三个参数 数字间隔2 (步长)。 5,7,9

七、函数

1.关键字 def 定义函数

def 函数名(参数):
	#函数体
	retrun 返回值

2.无返回值函数 内容为None 类型为NoneType

3.多个返回值

def fn():
    retrun 1,2  #变量用,隔开
x,y=fn()    #多个值接受
# x为1  y为2

4.不固定参数 *args和**kwargs

# 方法一:位置不定长 
def fn(*args):
    print(args)  
fn("tom",15)
# ("tom",15)  得到元组类型  

# 方法二: 关键字不定长 
def fn(**kwargs):   # 参数必须是key=vale
    print(kwargs)  
fn(name='张三')
#  {name='张三'} 得到字典类型  

5.匿名函数 lambda

lambda 传入参数:函数体(一行代码)

lambda x,y:x+y

6.函数类型定义

def add(x:int,y:int)->int:
    return x + y

#参数同ts  
#->类型  定义返回值

八、列表

1.下标可以是 负数

九、列表方法

1.arr.index(元素) 查询下标

arr=[1,2,3,4]
arr.index("1")  
#解析:元素存在返回下标,不存在 抛出异常
#返回:0

2.arr.insert(下标,元素) 指定位置插入元素

arr=[1,2,3,4]
arr.insert(0"5") 
#解析:插入 第一个参数下标 第二个参数元素
#改变后arr为 [5,1,2,3,4]

3.arr.append(元素) 末尾插入

arr=[1,2,3,4]
arr.append(5) 
#解析:尾部插入 相当于push
#改变后arr为[1,2,3,4,5]

4.arr.extend(其他列表) 末尾合并

arr=[1,2,3,4]
arr1=[56]
arr.extend(arr1) 
#解析:拼接数组   相当于concat 
#改变后arr为[1,2,3,4,5,6]
#----------------改变原数组

5.del arr[下标] 删除元素方法

arr=[1,2,3]
del arr[0]
#解析:删除指定下标数据
#改变后arr为[1,2]

5.arr.pop(下标) 删除元素方法-返回删除元素

arr=[1,2,3]
arr.pop(0)
#解析:删除下标为0的元素  返回删除具体元素
#返回:1
#改变后arr为[2,3]

6.arr.remove(元素) 删除指定元素方法

arr=[1,2,3,1]
arr.remove(1) 
#解析:删除指定匹配的第一个元素
#改变后arr为[2,3,1]

7.arr.clear() 清空数组

arr=[1,2,3,1]
arr.clear() 
#解析:清空数组
#改变后arr为[]

8.arr.count(元素) 统计列表内某元素的数量

arr=[1,2,3,1]
conut=arr.count(1)
#解析:统计列表内1的数量 只能统计第一层 二维数组里 无法统计
#返回:2

9.len(arr) 统计数组长度

arr=[1,2,3,1]
conut=len(arr) 
#解析:获取数组长度

10. sorted() 排序

#语法:sorted(容器,reverse) reverse表示正序或者反序   不传默认正序
list=[3,2,5,1]
sorted(list)  
#[1,2,3,4,5]

10. sort() 可用于复杂结构排序

#语法:sort(key=选择排序依据函数,reverse=True|Flase)

my_list = [["a",33],["b",55],["c",11]]
#定义排序方法
def choose_sort_key(element):
    return element[1] # 相当于安装每个元素的下标1排序
    
my_list.sort(key=choose_sort_key, reverse=True)
print(my_list)
             
#或者匿名函数
my_list.sort(key=lambda element: element[1], reverse=True)             

11.+ 合并两个列表

a=[1,2]
b=[3,4]
c=a+b #[1,2,3,4]
#----------------得到新数组不会改变原数组

12.* 快速生成重复数组

arr=[1,2]
print(arr*3) #[1,2,1,2,1,2] 重复三次

13.in 方法 判断数据是否在数组中

a=[1,2,3]
print(1 in a) #判断1是不是在a数组中  返回true 和false

14.max()最大值,min()最小值

#只适合于纯数字的列表
a=[1,2,3]
print(max(a)) #3
print(min(a)) #1

15.reverse 反序数组

a=["Z","N","2","1"]
a.reverse()
print(a)#["1","2","N","Z"]

十、元组及其方法

1.定义-通过括号或者关键之tuple

t1=(1,"hello",True)
t2=() 
t3=tuple() 
#------------如果是单独的元素必须加上逗号 不然不会认定为元组
t4=(1,)

2.元组方法

元组不支持修改 目前支持三个方法 find、count、len() 或者切片

arr=(1,"hello")
arr.find("hello")  #1
arr.count("hello")  #1
print(arr[0:1])#(1,"hello")  切片
len(arr)  #2

3.不支持修改(增加和删除)

如果元组嵌套列表,列表里面的值可以修改

十一、切片

1.序列

序列才能切片,不会修改原数据

序列:内容连续、有序、可使用下标索引的容器

列表、元组、字符串都可以视为序列

2.切片 序列[起始下标:结束下标:步长]

序列[起始下标:结束下标:步长]

三个参数:

起始下标:可省略 从头开始

结束下标:可省略 结尾结束 包头不包尾

步长:可以为负数 从数组倒序开始 默认步长为1 可省略

list=[0,1,2,3,4,5]
r=list[1:4] #123
r1=list[:] #[0,1,2,3,4,5]
r2=list[::2] #[0,2,4]

#步长为复数 开始结束省略
str="01234567"
#步长为复数
r3=str[::-1] #76543210
r4=str[::-2] #7531
#步长为复数 开始结束有值
r5=str[3:1:-1] #32

十二、集合

1.定义

1.用{}定义 set={"张三","李四","王五"}

2.用set() my_set=set() #定义空集合

#重点:集合无下标, 只有不可变的数据类型才能加入集合

2.添加add

python

set={"张三","李四","王五"}
set.add("HELLO") #{"张三","李四","王五","HELLO"}

3.删除remove

set={"张三","李四","王五"}
set.remove("王五")#{"张三","李四"}

4.随机取出元素 pop

set={"张三","李四","王五"}
ele=set.pop()
#取出元素后 改变原有的set  有返回值 ele就是随机取出的数

4.清空clear

set={"张三","李四","王五"}
set.clear()
#该集合被清空 {}

5.差级difference 或者 减法 -

set1={1,2,3}
set2={1,5,6}
set3=set1.difference(set2)
#解析:以set1为标准获得set2的差级
#set3为{2,3}  原有的集合不变

6.消除两个集合相同的 difference_update()

set1={1,2,3}
set2={1,5,6}
set1.difference_update(set2)
#相处set1相比set2相同的
#此时set1  为{2,3}
#set2不会发生变化

7.合并 unior

set1={1,2,3}
set2={1,5,6}
set3=set1.unior(set2)
#合并set1和set2 
#set3为{1,2,3,5,6}
#set1和set2不会发生改变

8.统计集合数量 len()

set1={1,2,3}
l=len(set1)#3

9. 并集 | 交集&

a={1,2,3}
b={3,4,5}

print(a|b) #{1,2,3,4,5}
print(a&b) #{3}

十三、字典

1.定义

使用{}或dict() 例:dict=dict()

存储元素为:键值对,例:{key:value,key:value}

2.取值

dict={"张三":12}
#方法一:
dict["张三"] 
#如果不存在的属性 会异常

#方法二:
dict.get("李四") #没有不会异常 返回None

3.删除pop

dict={"张三":12,"李四":14}
val=dict.pop("张三")
#参数为键名  
#返回被删除的元素 原字典{"李四":14}
#此时 dict为{"李四":14}

val=dict.pop("w","not exist")
#删除的键不存在会异常 第二个参数会默认给返回值不会异常
#此时 val 为not exist 

4.清空clear

dict={"张三":12,"李四":14}
dict.clear()

5.获取全部键 keys() 获取全部值 values()

dict={"张三":12,"李四":14}
for key in dict.keys() 
    	print(key) #张三 李四


for value in dict.values() 
    	print(value) #12  14

6.获取长度 len()

7.拷贝 copy()

d1={name:'1'}
d2=d1.copy()
#只能拷贝第一层

8.列表快速转换字典 dict.fromkeys()

list=["name","age","address"]
d3=dict.fromkeys(list,'Null') #第一个参数为列表  第二个参数为列表的值
#d3 = {"name":"Null","age":"Null","address":"Null"}

9.in 判断是否在字典中

dict={"张三":12}
print("张三" in dict) #true 

10.setdefault 和get类似 不存在会添加

dict={"张三":12}
dict.setdefault("李四",13)#返回13
#如果key存在返回 对应的value  
#如果不存在 就改变原字典 新增key 如果存在第二个参数有的话值 value为第二个参数
#没有第二个参数 value 默认为None

11.update 更新(合并)

dict={"张三":12}
dict1={"张三":13,"李四":14}

dict.update(dict2)
#dict 此时为{"张三":13,"李四":14} 
#原有的键和新的一样那么会更新新的  没有的会添加

12.删除popitem()

dict={"张三":12,"李四":14}
dict.popitem() #随机删除一个键值对

十四、内置函数

1.len()

获取长度

2.max()

最大元素

3.min()

最小

4.类型转换

  • list()
  • str()
  • tuple()
  • set()

参数为容器

5.dir()

大致理解为:查看对象属性和方法

dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;

带参数时,返回参数的属性、方法列表

6.isinstance()

#判断一个对象是否是一个已知的类型(是不是实例)
a = 2
isinstance (a,int)#True

isinstance() 与 type() 区别:

  • type() 不会认为子类是一种父类类型,不考虑继承关系。
  • isinstance() 会认为子类是一种父类类型,考虑继承关系。

7.print()多参数

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

#objects -- 复数,表示可以一次输出多个对象。输出多个对象时,需要用 , 分隔。
#sep -- 用来间隔多个对象,默认值是一个空格。
#end -- 用来设定以什么结尾。默认值是换行符 \n,我们可以换成其他字符串。
#file -- 要写入的文件对象。
#flush -- 输出是否被缓存通常决定于 file,但如果 flush 关键字参数为 True,流会被强制刷新。

十五、文件

1.打开文件open(name,mode,encoding) 和with open((name,mode,encoding) as f

1.1 open

# open(name,mode,encoding) # encoding不是第三顺位 传参需要指定encoding指定
# name:打开文件名或者具体路径

# mode:设置模式  只读、写入、追加   
# r  只读
# r+ 读写  不会主动生成文件
# w  写入 原有内容会被删除 如果该文件不存在会创建新文件 从头写
# a  表示追加 新内容会在已有内容后 如果不存在会创建新文件 从尾写
#  上面模式加b就是以二进制模式 例如 wb 以二进制写入
# encoding:编码格式 例utf-8 
#例: f=open("python.text","r",encodeing="UTF-8")

1.2 with open((name,mode,encoding) as f 通过语法可以自动关闭文件

 with.open("python.text","r",encodeing="UTF-8") as f
# f为文件对象名字

2.文件对象方法

2.1读取

1.文件对象.read(num) # 读取文件内容 num 表示读取字节数 比如10个字节 不传默认全部

如果连续调用两次 下一个会从上一个内容后继续读取

2.文件对象.readLines() #按行读取 读取成菜单 会读出\n 读取全部文字 返回一个列表

也会继承上次read读取内容 下一个会从上一个内容后继续读取

3.文件对象.readLine() #只读取一行 多次调用读取多行

######.可以使用for 读取 也会收到read影响

2.2关闭

文件对象.close()

解除占用

2.3写入

文件对象.write("hello")

写入到内存,一般保存图片之类的

文件对象.writelines(参数)

接受一个可迭代对象 比如列表或元组 需要换行必须在每个元素后加入\n

对象.flush()

刷新 保存

3.文件指针

#tell() 获取当前指针位置
文件对象.tell()


#seek() 移动指针
文件对象.seek(参数1,参数2)
#参数1 偏移量
#参数2 偏离相对位置 0是开头 1是相对当前位置唯一 2是末尾  如果以文本模式打开 只能取0 二进制无所谓

十六、异常

1.语法

try:
    # 代码
except:
    # 异常处理
else:
    #没有异常
finally:
    #有或者没有 都要执行

2.捕获指定异常

try:
    # 代码
except  NameError as e:
#except  [异常名 as 别名]:
    # 异常处理

# NameError 为指定异常  as e设置异常对象别名为e

#多个异常可以用(NameError,ZeroDivisonError)  括号包裹 逗号隔开
#捕获多个异常 可以用 Exception 或者直接except:

3.手动抛出异常 raise

#方法一
raise   #无参数  引发当前上下文捕获的异常   例 如果在except中就抛出当前异常 不在的或默认RuntimeError

#方法二
raise 异常名     #引发指定异常 

#方法二
raise 异常名(描述信息)     #引发指定异常  同时附带描述信息

4.自定义异常

class AuctionException(Exception): #必须继承Exception父类 自定义异常名字类
    pass #pass关键字占位

#使用
raise AuctionException("自定义错误内容")

try:
    XXXX
except AuctionException as e
	print(e) #自定义错误内容

十七、模块

1.导入

[from 模块名] import [模块 | 类 | 变量 | 函数 |][as 别名]

常用:

import 模块名

from 模块名 import 类、变量、方法

from 模块名 import *

import 模块名 as 别名

from 模块名 import 功能名 as 别名

例如:

import time

time.sleep(5)

from time import *

sleep(5)

2.自定义模块

import 自定义文件名

如果在自定义模块里 有调用函数方法 导入会直接调用

如果非要写 但是不想调用 用__main__

例: if name=="main": __name__是python内置变量 右键调试会把name变成main

fn()

自定义模块指定导出 限制于 import *

all=["fn"]

def fn():

XXX

def fn1():

XXX

此时 如果用*导入那么只能用fn 不能用fn1

3.内置常用模块

math模块

import math

math.ceil(x) #返回大于等于x的最小整数  向上取整

math.floor(x) #返回小于等于x的最小整数  向下取整

math.fabs(x) #取绝对值 返回一个浮点数

math.fsum([1,2,3])# 对数组内的数字 求和  返回浮点数

math.pow(x,y) #求幂 x的y次方

math.sqrt(x) #开方  返回浮点数

random模块

import random

random.random() #返回一个0到1的随机数  能取0取不到1   [0,1)

random.randint(a,b) #生成一个a和b之间的随机整数 包含a,b   [a,b]

random.randrange(a,b) #生成一个a和b之间的随机整数 包含a, 不包含b [a,b)

random.uniform(a,b) #生成一个a和b之间的随机浮点数 包含a,b   [a,b]

random.choic([]) #从列表里生成一个数

random.shuffle([]) #打乱列表的顺序 无返回值改变原址

random.sample([],n) #随机从列表里取出 n个数字 返回一个数组

十八、包

1.创建包

  1. 右键目录 创建 Python Package
  2. 取包名 会自动创建__init__.py 文件(不写东西都行,必须存在 代表包 方便引入模块)
  3. 在同级目录可以取模块名
  4. 如果要使用__all__就在__init__.py 文件里写
  5. 导入 直接包就可以 不需要单独操作模块

2.导入

import 包名.模块名字
from 包名 import 模块名字
from 包名.模块名字 import 方法

3.第三方包

1.安装

方法1:

# pip install 包名  (等同于npm 安装python自带)

#国内镜像
#pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名

方法2:

1.编辑器右下角 python版本号 点击

2.interpreter settings 点击

3.当前有包的列表 点击左上角加号

4.搜索 点击下 install package

5.右侧的Options 里可以加入镜像网址pypi.tuna.tsinghua.edu.cn/simple

十九、第三方库

1. json

转换为json格式:

import json
data=[{"name":"张三"}]
str=json.dumps(data,ensure_ascii=False) # ensure_ascii表示不使用编码 直接转

json转换原有格式:

import json
data='[{"name":"张三"}]'
l=json.loads(data)

2. PyEcharts

2.1. 折线图

from pyecharts.charts import Line
Tine = Line()
Tine.add_xaxis(["中国"])
line.add_yaxis ("GDp",[30,20,10])
Tine. render()
#右键运行后  同级会生成一个render.html文件 进入文件编辑器右上角自带预览

3. pymysql

操作mysq数据库

python3.0使用pymysql

python2.0使用mysqldb

import pymysql
#连接数据库
def connect_db():
    db=pymysql.connect(host="localhost",user="root",password="",charset="utf-8")
    cursor=db.cursor() # 返回操作数据库对象

	cursor.execute("select version()")#执行sql语句 此例子为:查询数据库版本
	data=cursor.fetchone()#查询结果   数据库版本号

	db.close()#关闭

二十、类

1.定义

class Student
	name=None
	def say(self,参数2):
        #要访问成员属性  需要self.name  self代表自己
        #参数2为形参
                
stu_1=Student()
stu_1.name="张三"
#和js不同的是不需要new关键字

2.封装

定义私有变量或方 使用__定义

class Student
	__name=None   #私有变量
	def __say(self):  #私有方法
      print()

#在类的内部可以使用 私有变量 实例访问不了

3.继承

1.如果子类没有定义自己的初始方法,则父类的初始方法自动会被调用,但是如果要实例化子类必须传入父类初始化方法的参数

2.如果在子类定义初始化方法,没有显示调用:父类会被覆盖。

显示调用 :

在子类init方法里:

父类名.init(参数)

定义:

class Phone2012(父类名字)
	类内容体


# 多继承 用逗号隔开
class Phone2012(父类名字1,父类名字2) 
	pass  # 使用pass关键字 占位 让语法不报错
#如果有同名成员或者方法 左边优先级最高

重写后-调用父类成员或方法:

使用super()或者父类名字.

class Phone2012(父类名字)
 #方法1
	def say(self):
      print(父类名字.父类属性) #用父类名称.属性或者方法可以调用父类方法
      print(父类名字.父类方法(self)) #如果调用父类方法 必须传入self

 #方法2
	def say(self):
      print(super().父类属性) #用super()关键字

4.类方法 @classmethod

  • 类方法可以直接类名调用,也可以实例去调用
  • 必须使用@classmethod床十七
  • 形参为cls
  • 类方法不能访问实例属性,只能访问类属性
class Student()
	def say(self,name):
        self.name=name
	@classmethod
	def classmethodemo(cls): #一般形参为cls
        print("这是个类方法") 

5.静态方法 @staticmethod

  • 使用@staticmethod 装饰器
  • 不能访问实例属性,也不能访问类属性
  • 可以直接类名调用,也可以实例去调用
class Student()
	def say(self,name):
        self.name=name
	@staticmethod
	def classmethodemo(): 
        print("这是个静态方法") 

二十一、类的魔术方法

1.init

#类的构造器 创建类时会默认调用
class Student
	name:"张三"
  	def __init__(self,name,age): # init方法创建对象自动执行 相当于js的构造器 参数为形参
        self.name=name  
        self.age=age  #如果类里没有定义 这一步会创建
         
stu_1=Student("张三",18)
#如果 没有使用str 会打印内存地址

2.str

class Student
	name:"张三"
    def __str__(self): # str方法适用于访问类对象的时候返回值 相当于js toString
        return f"我的名字是{self.name}"

stu=Student("张三")
print(stu) # 我的名字是张三

3.lt

class Student
	def __init__(self,age):
        self.age=age  
    def __lt__(self,other): # lt 用于类对象直接比较 返回一个布尔 self当前对象 other是其他对象
        return self.age<other.age

stu1=Student(15)
stu2=Student(14)
print(stu1 < stu2) #false

4.le

class Student
	def __init__(self,age):
        self.age=age  
    def __lt__(self,other): # le 同于lt 比较时候多了等于
        return self.age<=other.age

stu1=Student(15)
stu2=Student(14)
print(stu1 <= stu2) #false

4.eq

class Student
	def __init__(self,age):
        self.age=age  
    def __eq__(self,other): # eq 同于相等比较
        return self.age==other.age

stu1=Student(15)
stu2=Student(15)
print(stu1 == stu2) #true
#如果不使用eq 那么比较内存地址

二十二、类型注释

1.变量

#方法1使用: 同ts
var_1:int=10  #使用:定义

#方法2使用注释# type:
var_2=10 # type:int

2.函数

参数定义同ts

->类型 定义返回值

def add(x:int,y:int)->int:
    return x + y

#参数定义同ts  
#->类型  定义返回值

3.Union联合类型

导包:form typing import Union

Union[类型,...,类型]

form typing import Union
list :List[Union[int,str]]=[1,2,'hello']

二十三、线程

1.相关模块

1.threading python3之后的模块

2._thread :python3之前的thread模块的重命名 一般很少使用

2.创建线程

#方法一
import threading
t1=threading.Thread(target=参数1,args=(参数2)) 
# 参数1 为目标函数   参数2为参数  元组形式 多个逗号隔开
t1.start() #启动


#方法二  以类的方式
class MyThread(threading.Thread):
    def __init__(self,name):
        super().__init__() #调用父类的初始化方法 保证父类初始化成功
        self.name=name
	def run(self): #重写父类run方法 定义在新的线程类要完成的task
        print(123)
t1=MyThread("线程1")

3.方法

t1=threading.Thread(target=参数1,args=(参数2)) 
t1.start() #启动
t1.join() #让主线程等待 子线程执行

4.线程通信

from queue import Queue

q=Queue(maxsize=1)   #定义队列 队列最多消息为1
q.put() #发送消息  如果消息慢了会阻塞队列
q.get() #取出消息  每次取出消息 消息队列长度-1  如果长度为0  会阻塞线程

5.线程消息隔离(线程内部全局变量)

变量直接互不影响

import threading
local_data=threading.local()
local_data.name='local_data'
#此时主线程local_data.__dict__ 就为local_data

6.线程池

from concurrent.futures import ThreadPoolExecutor
#创建新的线程池对象  最大线程数为3
executor = ThreadPoolExecutor(max_workers=3)


#提交任务到线程池,参数只需要方法名字,不需要(),参数为方法的参数用逗号隔开,依次写  立即返回,不会阻塞主线程
#如果任务数超过任务书 会等待可用线程
task1=executor.submit(方法名称,参数xx) 


task1.done() #检查任务是否完成 返回true或false 存在问题(处于当前时间是否,不知道任务多久完成)

task1.cancel() #取消任务   该任务没有放入到线程池中才能取消成功  返回true和false

task1.result() #拿到任务结果 是阻塞方法会阻塞主线程

#---------获取全部结果---------

#as_completed  获取所有结果 像promise.all  
urls=[1,2,3]
all_task=[executor.submit(xxx,url) for url in urls]
for item as_completed(all_task):
	data=item.result() #获取返回结果 先执行先返回

# map  也是获取所有结果 
for item in executor.map(方法名,方法参数数组) #item 为结果  根据数组顺序得到结果

#wait() 方法
from concurrent.futures import wait
wait(all_task,return_when=FIRST_COMPLETED)  #让主线程等待
#return_when 值:FIRST_COMPLETED只要有一个执行完毕就执行主线程  ALL_COMPLETED所有执行完

7.线程同步信号量 Semaphore -控制最大线程数量并发

import threading
sem=threading.Semaphore(value=4)#最大线程为4


sem.acquire() #获取锁
sem.release()  #释放锁

二十四、进程

1.创建线程

import multiprocessing
#方法一
p1=multiprocessing.Process(target=参数1,args=(参数2))
# 参数1 为目标函数   参数2为参数  元组形式 多个逗号隔开

#方法二  以类的方式
class MyProcess(multiprocessing.Process):
    def __init__(self,name):
        super().__init__() #调用父类的初始化方法 保证父类初始化成功
        self.name=name
	def run(self): #重写父类run方法 
        print(123)
t1=MyThread("线程1")

2.方法

p1=multiprocessing.Process(target=参数1,args=(参数2))
p1.start() #启动
p1.join() #让主进程等待 子进程执行

3.进程通信

import multiprocessing

q=multiprocessing.Queue(maxsize=1)   #定义队列 最大进程数量1
q.put() #发送消息  如果消息慢了会阻塞队列
q.get() #取出消息  每次取出消息 消息队列长度-1  如果长度为0  会阻塞线程

4.进程池

#方法一:
from concurrent.futures import ProcessPoolExecutor
#参照线程池使用方法 一样


#方法二
import multiprocessing
pool=multiprocessing.Pool(multiprocessing.cpu_count()) #设置cpu核心数 不要大于当前cpu核心数
#multiprocessing.cpu_count() 方法获取当前cpu的核心数

result=pool.apply_async(函数名字,args(3,))#args(3,) 函数参数 是元组类型
popl.close() #必须在join前调用close
popl.join()#阻塞主进程
print(result.get()) #拿到子进程的结果


#获取多任务结果
for result in pool.imap(函数,[参数列表])
	print(result)#结果  按照输入顺序

for result in pool.imap_unordered(函数,[参数列表])
	print(result)#结果  先出先输出

5.进程和线程的区别,应用场景

多进程优点:独立运行,互不影响

多进程缺点:创建进程的代价非常大

多线程优点:效率比较高,不会耗费大量资源。

多线程缺点:稳定性较差,一个崩溃后会影响整个进程。

应用:

多进程适用场景:对于计算密集型任务,比较适合多进程。

多线程适用场景:适合 IO 密集型任务,比如文件读取以及爬虫等操作

二十五、协程

1.可迭代对象

1.1什么是可迭代对象

定义 了可返回一个迭代器__iter__

定义了可支持下标索引的__getitem__方法

1.2 如何判断是可迭代对象

#方法1
from collections import Iterable #迭代对象
print(isinstance([],Iterable))

#方法2
hasattr([],"__getitem__") #true  判断有无__getitem__方法

1.3 如何定义__getitem__方法

class Employee:
    def __init__(self,list):
        self.list=list
    def __getitem__(self,index):
        return self.list[index]

emp=Employee([1,2,3,4])
for i in emp:
    print(i)#1,2,3,4

2.迭代器对象

1.1什么是迭代器

迭代器就是实现了__next__和__iter__方法(缺一不可)的对象,就叫迭代器。

其中__iter__方法返回迭代器自身,

__next__方法不断返回迭代器中的下一个值

直到容器中没有更多的元素时则抛出Stoplteration异常,以终止迭代

二十六、锁

1.GIL全局解释器锁

GLL 全局解释器锁在什么时候会释放:

(1)当当前的执行线程在执行 IO 操作时,会主动放弃 GIL。

(2)当当前执行的线程执行了 100 条字节码的时候,会自动释放 GIL锁。

GIL 全局解释器锁是粗粒度的锁,必须配合线程模块中的锁才能对每个原子操作进行锁定

2.手动加锁

import threading
lock = threading.Lock()

lock.acquire()#获取锁
lock.release()#释放

#方法二: 使用with 自动获取和释放
with lock:
    global num
    num +=1

二十七、装饰器

1.使用

无参数
def timer(func):
    def doce(*args, **kwargs):
        print(123)
        func(*args, **kwargs)

    return doce


@timer #等同于 fn=time(fn)
def fn():
    print(456)

fn()
#先输出123
#后输出456
#相当于 给输出456的方法执行前 先执行123装饰器方法
有参数
def timer(name):
    print(name)

    def doce(func):
        def doce1(*args, **kwargs):
            func(*args, **kwargs)
        return doce1
    return doce


@timer("张三")
def fn(age):
    print(age)
fn(18)
有返回值
def timer(name):
    print(name)

    def doce(func):
        def doce1(*args, **kwargs):
            result = func(*args, **kwargs)
            return result

        return doce1

    return doce


@timer("张三")
def fn(age):
    print(age)
    return 123
print(fn(18))

2.定义装饰器

#(1)被装饰函数带有参数或不带参数
def deco(func):
    def inner(*args,**kwargs):
        func(*args,**kwargs)
        return inner

# (2) 装饰器本身带参数
def deco1(parma): # param是装饰器本身的参数
    def outer(func): # 以被装饰的函数名作为参数
   		def inner(*args,**kwargs)
				func(*args,**kwargs)
		return inner
	return outer

#(3) 被装饰函数带返回值
def deco2(parma): # param是装饰器本身的参数def
	def outer(func): # 以被装饰的函数名作为参数
		def inner(*args,**kwargs):
			result = func(*args,**kwargs) # 接收到被装饰函数的返回值
            return result# 返回被装饰函数的返回值
		return inner
	return outer

二十八、event对象

import threading
event = threading.Event()

#重置event对象 使所有的event事件都处于待命状态
event.clear()
#阻塞线程 等待event指令
event.wait()
#发送event指令,使得设置该event事件线程执行
event.set()

二十九、Condition对象

import threading
cond = threading.Condition()

class Ximige(threading.Thread):
	def __init__ (self, cond, name):
        threading.Thread.__init__(self, name=name) #父类方法
    	self.cond = cond
    def run(self):
        self.cond.acquire() #获取锁
        self.cond.wait() #等待
        self.cond.notify() #唤醒其他wait状态的线程
    	self.cond.release() #释放锁
ximige=Ximige(cond,'西米哥')

未完待续

转载自:https://juejin.cn/post/7244802984119320636
评论
请登录