python基础和第三方库 笔记(python基础完结包括高级用法,第三方库持续更新中...)

python基础

注:本笔记面向有一定基础的人
本笔记是本人快速复习python过程中记录的,不适合零基础的人学习python的主工具,可以作为辅工具,本笔记记录了入门阶段常用操作,如有错误的地方,希望读者不吝赐教。

第一部分

1.1变量

# 1 打印变量类型
print(tpye(变量名))

# 2 打印变量/对象 内存id
print(id(变量))

# 3 list -- 列表
c=[10,2,1]

# 4 tuple -- 元组
c=(10,2,3)   

# 5 set -- 集合
c={10,2,1}

# 6 dict -- 字典
c={
    '1':1,
    '2':2,
}

1.2格式化输出,输入

学习内容 :格式化符号,格式化方法,转义字符

格式符号转换
%s字符串
%d有符号十进制数
%f浮点数
%.3f   #保留几位小数
print('我的名字是%s 今年%d岁了' % (name,age))   #输出内容和数据绑定用%链接
%06d   #输出6位整数用0填充

#格式化字符串f'{表达式}'
print(f'我的名字是{变量名},今年{age}岁了')

#转义字符
\n \t
#print默认以\n作为end,但可以显示声明其他结束符号
print('hello',end='...')    

#输入  input当作字符串处理,交给一个变量
input("提示信息")

1.3类型转换

函数说明
int(x[,base])。。。
flot(x)。。。
str(x)。。。
⭐eval(str)计算字符串中有效的python表达式,返回一个对象
tuple(S)。。。
list(S)。。。
#把字符串里面的表达式转换为合适的类型
print(eval('[100,20]'))   #[100,20]

1.4运算符

#逻辑运算符
and or not

#python可以用类数学写法,下面写法是合法的语法
15<=a<=70

#三目运算符 化简简单的ifelse语句
c=a if a>b else b  #如果条件成立 c=a 否则c=b

1.5循环

# for和while后面都可以跟else 表示循环正常结束后执行,brek为非正常结束
while t<10:
    ...
else:
    ...

1.6⭐字符串

#切片  [开始:结束:步长 ] 其中若为二维数组则还可以这么些[开始:结束:步长,开始:结束:步长]  左闭右开不包括结束符,但是包括开始符、
#其中-7表示倒数第7个


#下列函数用法变量名.方法名
#---------------------查找--------------------
#find(子串,开始位置,结束位置)    查找是否存在某字串 返回第一次找到该字串所在母串中的位子 
mystr = 'hello world and itcast and itheima and Python'
print(mystr.find())  #12
#rfind()与find()相同,从右往左查找
#count()和find()的参数相同,返回出现次数
#index()与find()完全相同,find未找到返回-1  index未找到返回异常

#---------------------修改1--------------------
#replace(旧字串,新字串,替换次数)  把旧字串替换为新字符串 
#split(字符串,次数)  返回是一个列表,用字符串分割split数组,其中次数代表的是分隔符出现的次数,次数为2分割后数据为3个
#join(多字符串组成的序列)    !用法特殊!
'...'.join(['12','34'])  #12...34

#---------------------修改2--------------------
#capitalize()  第一个大写
#title()  每个单词首字母大写
#lower() 大写转小写
#upper()  小写转大写


#lstrip()    删除左侧空白
#rstrip()	 删除右侧空白
#strip()	 删除两侧空白

#---------------------格式化--------------------
#ljust(长度,填充字符)  左对齐 第二个参数不些默认空格填充
#rjust 	右对齐
#center  中间对齐
mystr='hello'
print(mystr.ljust(10,'.'))  #hello.....

#---------------------判断--------------------
#startwith(字串,开始,结束) 判断是否为字串开头  返回布尔类型
#endwith(字串,开始,结束)  判断是否为字串结尾
#isdigit()是否全是数字
#isalnum()是否是由字母和数字的组合组成
#isspace()是否全是空格

#注字符串的拼接直接用+号就可以

1.7⭐列表

#index   和字符串相关的函数一样
#count()   和字符串相关的函数一样
#len()   列表里面元素的个数

#判断某个数据是否存在 
in / not in
'lily' in name_list  #如果lily在name_list中返回true  
'lily' not in name_list

#添加数据
#append(元素) 把元素添加到列表尾  如果是序列则把整个序列添加进列表
#extend()   同上,但参数可以是一个序列,并且把该序列所有元素依次添加进列表
#insert(位置下表,数据)   指定位置增加数据

#删除数据
#del(数组变量/下标)     删除列表 把整个列表删除 或者删除下标元素
#pop()      删除指定位置元素 默认删除最后一个数据  返回被删除的数据
#remove()  删除指定元素
#clear()  清空

#修改
#reverse()   反转列表
#sort(key=None,reverse=False )    列表 reverse为False 升序

#列表复制
#copy()  注:python中列表只有一个存储,所有的名字都执行同一个空间,可以当作指针理解,因此修改列表需要复制一份然后再删除

1.8元组

元组中的数据不能修改 ,元组数据不能修改,但是元组里面有列表,列表中的数据可以修改

t1=(1,2,3)
print(t1[1])  # 2
print(t1.index(2)) #1

t1=(1,2,[1,2])
t1[2][0]=2
print(t1)   #(1,2,[2,2])

#只有一个元素的元组要这么写
(1,)

1.9字典

#新增数据
dic['1']='2'  #如果dic中没有‘1’这个key值则添加新的键值对,如果key存在则修改

#删除
#del()同列表
#clear()同列表用法相同

#查找
dic['1']
dic.get('1',2)  #如果查找不到key为'1'则返回默认值2

#遍历字典
#counts.items()为字典的迭代器,获取到的是字典中的键值对元组
dic1={'name':1,'age':2,'gender':3}
for key,value in dic1.items():
    print(f'{key}={value}')  
#!!对字典进行拆包得到的是key!!

1.10集合

去重,和列表相比 集合里面没有重复的数据

#创建集合
s1={1,2,3}
s1=set()  创建空集合  #注:s1={}表示s1为空字典

#增加数据
#add()  s1.add(10)  如果重复不进行任何操作
#updata()   !注意增加的数据是列表

#删除数据
#remove  删除指定数据,   !没有不报错!
#discard()  删除指定数据   !没有报错!
#pop() 随机删除数据并返回删除的数据

#查找数据
in / not in

第二部分

2.1公共运算

2.1.1运算符
运算符描述支持的容器类型
+合并字符串、列表、元组
*复制字符串、列表、元组
in元素是否存在字符串、列表、元组、字典
not in元素是否不存在字符串、列表、元组、字典
2.1.2公共方法
函数描述
len()容器元素个数
del del()删除
max()容器元素最大值
min()容器元素最小值
range(start,end,step)生成从start到end的数字,步长为step,供for循环使用
enumerate(可遍历对象,start=0)函数用于将一个可遍历的数据对象组合为一个索引序列,同时列出数据和数据下表,一般用在for循环当中。start为遍历对象下表起始值(计算机默认为0可以手动调节为1) 返回值为index,value
2.1.3容器类型转换
  • tuple()
  • list
  • set()

2.2推导式

更有风格的python代码书写,代码量更少

2.2.1列表推导式

用一个表达式创建一个有规律的列表,或者控制一个有规律的列表

  • 创建有规律的列表
list1=[i for i in range(10)]   #其中左面的i是回填的数据格式,右面的i是生成的i 还可以在继续对i添加if条件,满足条件才回填
print(list1)
# [0,1,2,3,4,5,6,7,8,9]
#创建偶数的列表
list1=[i for i in range(10)  if i%2==0 ]   
print(list1)
# [0,2,4,6,8]
#多for循环
list1=[(i,j) for i in range(1,2) for j in range(3)]   
print(list1)
#[(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
2.2.2字典推导式

快速合并列表为字典或者提取字典中目标数据

  • 创建字典
dic={i:i**2 for i in range(1,5)}
print(dic)
#{1: 1, 2: 4, 3: 9, 4: 16}
  • 把两个列表合并为一个列表
list1=['张三','李四','王五']
list2=[18,20,13]
dic={list1[i]:list2[i] for i in range(len(list1)) }
print(dic)
#{'张三': 18, '李四': 20, '王五': 13}
  • 提取字典中的目标数据
#提取counts中的value满足一定条件的数据
counts={'map':123,'hp':1233,'dell':298,'acer':981}
count1={key:value for key,value in counts.items() if value>=200}   #!注: counts.items()为字典的迭代器,获取到的是字典中的键值对元组
print(count1)
#{'hp': 1233, 'dell': 298, 'acer': 981}
2.2.3集合推导式
list1=[1,1,2]
#返回list1中每个数据的二次方组成的集合
set1={i **2 for i in list1}
print(set1)
#{1,4}

2.3函数

#查看函数说明文档
def 函数名(参数):
	"""说明文档"""
	代码
	......
help(函数名)  
2.3.1修改全局变量
a=100
def test():
    global a    #声明a为全局变量的a
    a=200
    return

text()
print(a)
#200
2.3.2参数写法

*args **kwargs

其中的*可以看作一个运算,可以把1,2,3,4这种用逗号隔开的数据变为一个元组(1,2,3,4)也可以把(1,2,3,4)变为1,2,3,4

**则是把age=20,name='asd'用逗号隔开的key=value复制变为一个字典,反过来也可以把字典变为key=value赋值

  • 位置参数
def function(name,age,gender):
    .....
# 传入参数的时候根据位置传入对应的形参
  • 关键字参数
fdef function(name,age,gender):
    .....
function('张三',gender='nv',age=18)
# 位置参数放在关键字参数之前,关键字参数顺序对结果无影响
  • 缺省参数
def function(name,age,gender,test='1'):
    .....
function('张三',18,'男')   #此时默认test=1
function('张三',18,'男',2)   #此时test=2
  • 包裹位置传递(不定长传递)得到的是一个元组,位置和传入时相同
#  默认用*args作为不定长参数的传递   
def user_info(*args):  
    #这里的args是一个元组
    print(args)
    
#('Tom',)
user_info('Tom')
#('Tom',18)
user_info('Tom',18)
  • 包裹关键字传递(不定长传递)得到的是一个字典
def user_info(**kwargs):
    print(kwargs)
    
user_info(name='tom',age=18,id=110)
2.3.3交换变量
a,b=b,a  #交换ab的值
3.3.4引用

在python中,值是靠引用传递过来的

a=1,b=a 此时b就是a的引用

函数值传递过程中实参的传送可以是引用

a=1
b=a  #此时b是a的引用,指向同一块内存空间
#id()可以判断两个变量是否是同一个值的 引用可以理解为id是内存地址的标识
  • 不可变类型的引用(整形,浮点型,字符串,元组)
a=1
b=a
#此时id(a)与id(b)是一样的
a=2
#此时id(a)与id(b)是不一样的  并且a=2,b=1   a改变了因此开辟了一块新的空间存储新的值
  • 可变数据类型的引用(列表,字典,集合)
aa=[10,20]
bb=aa
bb[0]=11
print(aa)
#[11,20]
#注意通过函数传送的值也是引用,函数体内如果要修改数组,记得copy一下
在修改数组
2.3.5⭐lambda表达式

如果函数只有一个返回值,并且只有一句代码,可以使用lambda简化

lambda 参数列表: 表达式(返回值)

fn2=lambda :100   #fn2是一个函数
print(fn2)      #打印的是内存地址
print(fn2())      #是函数返回值
  • 参数形式
pritn(fn1(1,2,3))fn1 =lambda a,b:a+b   #有参数

fn1 =lambda a,b,c=100:a+b+c   #默认参数

fn1 =lambda *args:agrs   #可变参数 元组
pritn(fn1(1,2,3))

fn1 =lambda **args:agrs   #可变参数 字典
pritn(fn1(name='c',age=2))
  • lambda应用
fn1= lambda a,b : a if a>b else b
print(fn1(1000,500))   #1000

#列表(里面是字典)根据字典某个确定key的value值进行排序
student=[{'name':'ad','age':20},{'name':'a','age':30},{'name':'ab','age':10}]
student.sort(key=lambda x:x['age'])   #这里的x代指列表里面的字典  根据字典中的name的value值排序
print(student)   #[{'name': 'ab', 'age': 10}, {'name': 'ad', 'age': 20}, {'name': 'a', 'age': 30}]

2.3.7⭐高阶函数

把函数作为参数传入,函数式编程的体现,

  • 思路分析
def function(a,b)
	return abs(a)+abs(b)
def function(a,b)
	return round(a)+round(b)

#上面两个函数可以写为一个
def function(a,b,f)  #f是一个函数
	return f(a)+f(b)

result=function(1,2,abs)
result=function(1.2,2.7,round)
  • 内置高阶函数
函数作用
map(func,lst)将传入的函数变量func作用到lst变量的每个元素中,结果返回迭代器(python3)返回(需要进行过类型变换)
reduce(func,lst)func必须有两个参数。作用是func(func(func(func(func(func(a,b),c),d),e),f),g)
filter(func,lst)过滤到不符合func条件的元素,返回一个filter对象,如果转换为列表用list()
#----------------map(func,lstt)-----------------
list1=[1,2,3,4,5]
def func(x):
    return x**2
result=map(func,list1)
print(result)  #内存地址
print(list(result))   #列表

#----------------reduce(func,lstt)-----------------
#list1累加
def func(a,b):
    return a+b
result=reduce(func,lst1)
print(result)  #整形

#----------------filter(func,lstt)-----------------
#需要的是一个返回布尔型的函数
def func(a):
    return x%2==0  
result=filter(func,lst1)
print(result)  #内存地址
print(list(result))   #列表

2.4面向对象

类名函数 满足大驼峰命名 变量满足小驼峰

print(类名.__mro__)   #打印当前类所继承的父类及其层级关系
print(类名/实例名.__dict__)  #打印类或者实例里所有的属性和方法组成的字典
2.4.1python面向对象特点
  • self == this
# self指代调用该函数的对象,可以通过self访问该对象的数据 相当于this
class Washer():
    def was(self):
        print(self)


test = Washer()
print(test)
print(test.was)
  • 多例
class Washer():
    def was(self):
        print(self)


test1 = Washer()
test2=Washer()
#test1 与test2 不一样,python的对象是多例的
  • 类的属性
#类外面添加属性  这是和别的编程语言不同的
class Washer():
    def was(self):
        print(self)
test = Washer()

test.widteh=500
test.height=800

#类的外面获取属性  对象名.属性名
 
#类里面获取属性  self.属性名   只能获取对象拥有的属性
2.4.2⭐魔法方法
# __xx__()形式的函数叫做魔法函数,用作特殊作用
  • 初始化魔法函数
class Washer():
    def __init__(self):  #在创建对象的时候自动执行      无参
        self.width=500
        self.heigth=300
    def was(self):
        print(self)
test = Washer()

class Washer():
    def __init__(self,width,height):  #在创建对象的时候自动执行      无参
        self.width=width
        self.heigth=height
    def was(self):
        print(self)
test = Washer()
  • str魔法方法
#打印对象实际上打印的是对象的内存地址,如果定义了__str__方法,那么就会打印从这个方法中return的数据
class Washer():
    def __init__(self):  #在创建对象的时候自动执行      无参
        self.width=500
        self.heigth=300
    def was(self):
        print(self)
    #str魔法方法大多都是介绍该类的作用
    def __str__(self):  
        return "这是一个洗衣机类"
result=Washer()
print(result)  #这是一个洗衣机类
  • del魔法方法
class Washer():
    def __init__(self):  #在创建对象的时候自动执行      无参
        self.width=500
        self.heigth=300
    def was(self):
        print(self)
    #str魔法方法大多都是介绍该类的作用
    def __del__(self):
        print("对象已经删除")
result=Washer()   
del result  #对象已经删除  注意不用手动del,在程序执行完后会自动删除对象,执行del魔法方法
  • call魔法方法

带有call魔法方法的类可以当作函数一样调用

class Check(object):
    def __call__(self,*args,**kwargs):
        pritn("我是call方法")
c=Check()
c()   #向函数一样调用该类对象的call方法
2.4.3继承/私有权限
#object是继承,默认继承顶级类就是object类
class 类名(object):
	代码
    
print(类名.__mro__)   #打印当前类所继承的父类及其层级关系

继承默认继承父类的所有属性和方法

多继承默认使用第一个类的同名属性和方法

  • 方法重写
#子类重写父类同名方法,默认使用子类的同名方法,那么如何利用父类的同名方法呢

class Master(object):
    def __init__(self):
        self.kongfu='123'
    def make_cake(self):
        print(f'利用{self.kongfu}')
class Prentice(Master):
    def __init__(self):
        self.kongfu='1'
    def make_cake(self):
        print(f'利用{self.kongfu}')
    #在子类中把和父类重名的方法重新写一遍,Master代指父类
    def father_master_make_cake(self):
        Master.__init__()
        Master.make_cake()

  • super()调用父类的方法
# 调用本类的直接父继承的方法  遵循mro类属性顺序,适合单继承使用
super().方法名
  • 私有属性/方法

私有权限不会继承给子类

# 属性名以__开头的是私有属性,__开头的是私有方法
class Master(object):
    def __init__(self):
        self.kongfu='123'
        self.__money=20000
    def __info_print(self):
        print(f'我的资产{self.__money}')

#获取和修改私有属性  只能在类内获取和修改私有属性
class Master(object):
    def __init__(self):
        self.kongfu='123'
        self.__money=20000
    def __info_print(self):
        print(f'我的资产{self.__money}')
    #获取和修改私有属性的值
    def get_money(self):
        return self.__money=money:
    def set_money(self,money):
        self.__money=money

2.5.4多态

子类重写父类的方法,传入不同的子类,执行不同的方法

class Dog():
    def work(self):
        print("开始工作")
class ArmyDog(Dog):
    def work(self):
        print("追击敌人")

class DrugDog(Dog):
    def work(self):
        print("追击毒品")

class ClassificationDog():
    def work(self,dog):
        dog.work()

cd=ClassificationDog()
ad=ArmyDog()
dd=DrugDog()
cd.work(ad)   #追击敌人
cd.work(dd)   #追击毒品
2.5.5类属性/方法/静态方法

类拥有的属性,被该类所有的对象所共享,可以用实例对象访问,也可以用类来访问

  • 设置和访问类属性
class Dog(object):
    tooth=10      #这就是类属性
  • 修改类属性

类属性只能通过类修改,无法通过实例修改,如果实例修改类属性,则是创建和类属性同名的实例属性而已

class Dog(object):
    tooth=10      #这就是类属性
    
  
wangcai=Dog()
Dog.tooth=12
print(wangcai.tooth)  #12
  • 类方法

需要用装饰器@classmethod

类方法用来获取类私有属性 类方法用类名或者实例对象名访问

class Dog():
    __tooth=10
    @classmethod
    def get_tooth(cls):   #cls指代的是类,self指代的是实例对象
        return  cls.__tooth

test=Dog()
print(test.__tooth)  #报错
print(test.get_tooth)  #10
  • 静态方法

用装饰器staticmethod来修饰,不需要传递对象不需要传递实例对象 即没有self或者cls

静态方法也可以通过实例对象和类对象访问

class Dog():
    @staticmethod
    def info_print():
        print('这是一个狗类用于创建狗实例...')
test=Dog()
test.info_print()
Dog.info_print()

2.5异常

2.5.1错误异常
  • 写法结构
try:
    可能发生异常的代码
except:
    发生异常后执行的代码
  • 捕获指定异常类型/打印异常描述
#单个
try:
    可能发生异常的代码
except 异常类型:
    发生异常后执行的代码
#多个   
try:
    可能发生异常的代码
except (异常类型1,异常类型2):
    发生异常后执行的代码
    
#捕获异常描述类型
try:
    可能发生异常的代码
except (异常类型1,异常类型2) as result:
    print(result)
    
#!!其中Exception代表所有异常!!
  • 异常的else finally
try:
    可能发生异常的代码
except Exception as result:
    print(result)
else:
    没有异常后执行的代码
finally:
    无论如何都会执行的代码
  • 异常传递

异常可以嵌套

import time
try:
    f=open('test.txt')
    try:
        while True:
            content=f.readline()
            if(len(content)==0):
                break
            time.sleep(2)
            print(content)
    except:
        print('意外终止了读取数据')
    finally:
        f.close()
        print('关闭文件')
except:
    print('无法打开该文件')
2.5.2自定义异常

不符合程序逻辑要求 把其设置为异常来提醒用户

  1. 自定义异常类
  2. 抛出异常 raise关键字加异常类(如有初始化参数写在这里)
  3. 捕获异常
# 自定义异常
class ShotrInputError(Exception):
    def __init__(self, length, minlength):
        self.length = length
        self.minlength = minlength

    # 异常抛出信息
    def __str__(self):
        return f'您输入的长度为{self.length},不能少于{self.minlength}'
# 测试类
def test():
    try:
        con = input('请输入密码:\n')
        if (len(con) < 10):
            # raise抛出异常
            raise ShotrInputError(len(con), 10)
    except ShotrInputError as result:
        print(result)
    else:
        print('密码已经输入完成')
# 测试开始
test()

2.6模块和包

2.6.1自己写的模块

如果import则会导入所有,包括测试,那么如何让测试只在模块内调用呢?

# 自定义异常
class ShotrInputError(Exception):
    def __init__(self, length, minlength):
        self.length = length
        self.minlength = minlength

    # 异常抛出信息
    def __str__(self):
        return f'您输入的长度为{self.length},不能少于{self.minlength}'


def test():
    try:
        con = input('请输入密码:\n')
        if (len(con) < 10):
            # raise抛出异常
            raise ShotrInputError(len(con), 10)
    except ShotrInputError as result:
        print(result)
    else:
        print('密码已经输入完成')


# 其中如果在当前模块运行则__name__==__main__,如果不是在当前模块,比如被别人导入了本模块 ,则__name__等于模块名
if __name__ == '__main__':
    test()

搜索模块顺序

  1. 当前目录 (注:自己的文件名不要和已有的模块名重复)
  2. pythonpath目录下的每个目录 虚拟环境的目录
  3. 默认路径
2.6.2all列表

如果一个模块中有all变量,,使用from xxx import *导入时,只能导入这个列表中的元素(即把模块功能写近all列表中,导入的时候只导入注册到all列表中的方法)

#这是一个模块
__all__=['test1']

def test1():
    print('test1')
def test2():
    print('test2')
#只有test1方法能被导入到其他文件中
2.6.3包

文件夹,里面是一些有联系的模块。包里面有个init.py文件,用于控制导入包的内容

init.py 里面添加all=[],里面写上允许导入的模块名

第三部分

在本部分中将介绍python的高级用法包括进程线程 装饰器等

3.1程序的并行和并发

3.1.1多进程

创建子进程实际上把主进程的资源拷贝了一遍,他们俩之间互不干扰。因此不共享全局变量

  • 创建子进程
# 1 导入模块 multiprocessing 创建进程对象 并启动
def func_a():
    for i in range(5):
        print('A进程在执行')
def func_b():
    for i in range(5):
        print('B进程在运行')
        
if __name__ == '__main__':
    process1=multiprocessing.Process(target=func_a)
    process2=multiprocessing.Process(target=func_b)
    process1.start()
    process2.start()
# 2 执行带有参数的任务
process1=multiprocessing.Process(target=func_a,args=(1,2,3))  #args传送参数元组方式,kwargs后面跟字典
process2=multiprocessing.Process(target=func_b)
process1.start()
process2.start()
  • 获取进程编号
# 1 获取进程编号
import os
getpid()  #获取当前运行进程编号
getppid()  #获取当前父进程编号
  • 进程结束顺序

主进程等待所有子进程工作后才会结束

# 1 主进程默认等待所有子进程的执行
def func_a():
    for i in range(10):
        print('工作中...')
        time.sleep(0.2)
if __name__ == '__main__':
    process1=multiprocessing.Process(target=func_a)
    process1.start()
    time.sleep(1)
    print('主进程工作完成')

# 2 主进程结束后,子进程自动结束 【1 设置子进程为守护主进程,主进程完成后,子进程会自动结束】【2 也可以手动销毁子进程】
process1.daemon=True 
peocess1.start()   #【方法一】

process1.terminate()   #【方法二】

3.1.2 多线程
  • 多任务可以利用多线程使用,进程会分配资源,线程只是执行,不会分配资源

    比如:要给两人两天两个窗口 如果用多进程则每个窗口都有资源,如果用多线程就会节省资源

  • 线程之间的执行是无序的,由cup调度决定

  • 线程之间共享全局变量

# 1 创建多线程  【和多进程类似只不过把名字变了】
import threading
import time
def func_a():
    for i in range(10):
        print('工作中...')
        time.sleep(0.2)
def func_b():
    for i in range(10):
        print('学习中...')
        time.sleep(0.2)
if __name__ == '__main__':
    thread1=threading.Thread(target=func_a,daemon=True)
    thread2 = threading.Thread(target=func_b)
    thread1.start()
    thread2.start()
    time.sleep(1)
    print('主进程工作完成')
    
# 2 设置守护主线程  
thread1.setDaemon(True)

# 3 线程对象信息
info=threading.current_thread()
print(info)

# 4 验证多线程之间共享全局变量
my_list=[]
def func_a():
    for i in range(10):
        my_list.append(i)
        print('add:',i)
        time.sleep(0.2)
    print(my_list)
def func_b():
    print(my_list)

if __name__ == '__main__':
    #创建子线程
    thread1=threading.Thread(target=func_a)
    thread2=threading.Thread(target=func_b)
    thread1.start()
    thread1.join(timeout=10)   #等待本线程执行完毕,可以设置超时时间
    thread2.start()
  • 同步/互斥
# 1 互斥锁的使用
mutex=threading.Lock()  #获取一个锁  【在主进程中】
mutex.acquire()   #在子线程中上锁       
mutex.release()   #在子线程中解锁     

3.2函数进阶

3.2.1函数参数

函数名实际上存放的是函数的地址

# 1 例子1
def func01():
    print("func01 is shwo")

print(func01)
func02=func01
func02()  #【func01 is shwo】

# 2 例子2
def func01():
    print("func01 is shwo")
def fun(func):
    func()
fun(func01)   #【func01 is shwo】

3.2.2闭包

函数内部的局部变量,在函数运行完后,就被销毁了。但有时候,我们需要保存,函数执行过程中的局部变量。

定义:

  1. 在函数嵌套前提下,
  2. 内部函数使用了外部函数的变量,
  3. 并且外部函数返回了内部函数

我们把这个使用外部函数变量的内部函数称为闭包

# 1 闭包例子
def func_out(num1):  #【创建函数闭包】
    def func_inner(num2):
        num=num1+num2
        print('num:',num)
    # func_inner就是闭包
    return func_inner
f=func_out(10)  #f是闭包实例,是一个闭包  【函数闭包实例化】
f(20)
f(30)   #可以看到10使用了多次

# 2 闭包的使用
	'''
        张三:到北京了么?
        李四:到北京了
        张三:北京冬天冷么?
        李四:冷!
	'''
def func_out(name):
    def func_inner(info):
        print(f'{name}:{info}')
    return func_inner
ZhangSan=func_out("张三")
LiSi=func_out("李四")
ZhangSan("到北京了么?")
LiSi("到北京了")
ZhangSan("北京冬天冷么?")
LiSi("冷!")

# 3 闭包可以修改外部变量   nonlocal
def func_out(num1):
    def func_inner(num2):
        nonlocal num1     #【声明外部函数变量】
        num1=num2+10
        print('num1:',num1)
    print(num1)
    func_inner(20)
    print(num1)
    return func_inner

f=func_out(10)
3.2.3装饰器

在不改变函数源代码的情况下,给函数增加新的功能

封闭开放原则:源代码不修改,但是可以根据实际扩展需求(框架设计)

装饰器的本质是闭包

  • 装饰器基础(无参数)
# 1 例子1
def comment():
    print("发表评论")
def check(fn):   #【定义一个装饰器】
    def inner():  #【增加新功能】
        print("请登录")  
        fn()    #【不要忘记原有的功能】【此时inner就变为了一个既有新功能又有原功能的函数(还是原函数)】
    return inner
comment=check(comment)   #用装饰器装饰一下函数 【即增加新的功能】
comment()

# 2 例子2  使用语法糖写法
def check(fn):   #【定义一个装饰器】
    def inner():
        print("请登录")
        fn()
    return inner

@check   #comment=check(comment)
def comment():
    print("发表评论")
comment()
#【通过本例子读者应受到启发,可以把一些固定不变的语法放到装饰器中,然后我们只需要写不同的内容函数,然后用该装饰器装饰一下即可。】

# 3 装饰器的使用,统计函数的执行时间
import time
def get_time(func):
    def inner():
        start=time.time()
        func()
        print("程序执行时间为:",time.time()-start)
    return inner

@get_time
def func():
    for i in range(100000):
        print(i)
func()  #装饰后,执行该函数的时候执行完会打印函数的执行时间
  • 通用装饰器
# 1 装饰有参数的函数(一般参数)
def logging(func):
    def inner(a,b):  #inner内部参数和被装饰函数的参数一样多
        func(a,b)   #被装饰的函数
    return inner
@logging
def sum_sum(a,b):
    print(a+b)
sum_sum(1,2)
#【显然这么做泛用性大大降低了,不同的原始函数可能有不同的参数,仅仅一个装饰器无法胜任】

# 2 装饰带有返回值的函数
def logging(func):
    def inner(a,b):
        result=func(a,b)     #装饰器获取原函数的返回值
        return result        #装饰器把原函数的返回值返回
    return inner
@logging
def sum_sum(a,b):
    return a+b
print(sum_sum(1,2))

# 3 通用装饰器(任何参数和返回值)
def logging(func):       
    def inner(*args,**kwargs):
        #新功能增加
        result=func(*args,**kwargs)
        return result
    return inner
@logging
def sum_sum(*args,**kwargs):
    print(args,kwargs)
sum_sum(1,2,2,3,5,6,age='20',name='asdf')
  • 多个装饰器装饰一个函数

谁距离原函数近,先装饰谁

# 1 多个装饰器例子
def checkuser(func):
    def inner(*args,**kwargs):
        print("登录验证")
        result=func(*args,**kwargs)
        return result
    return inner

def checkinfo(func):
    def inner(*args,**kwargs):
        print("审核通过...")
        result=func(*args,**kwargs)
        return result
    return inner
@checkuser
@checkinfo
def comment():
    print("发表评论")

comment()
  • 带有参数的装饰器

使用装饰器装饰函数的时候可以传入指定参数,注意此时的参数是装饰器的参数而不是函数的参数

# 1 例子1
def logging(flag):          #在装饰器外面添加一个接受参数的函数,然后把真正的装饰函数返回
    def decorator(func):
        def inner(num1,num2):
            if flag=='+':
                print("正在计算假发")
            elif flag=='-':
                print("正在计算剑法")
            result=func(num1,num2)
            return result
        return inner
    return decorator

@logging('+')
def add(a,b):
    result=a+b
    return result

print(add(1,4))
  • 类装饰器(使用情况很少)
# 1 例子
class Check(object):
    def __init__(self,fn):   
        self.__fn=fn

    def __call__(self,*args,**kwargs):
        print("登录")
        self.__fn()
@Check    #【comment=Check(comment)->实际上创建了一个类的实例,comment()就调用该实例的call方法】
def comment():
    print('发表评论')
comment()

3.3高级语法

3.3.1property属性

负责把类中的方法当作属性去使用

获取私有属性的方法可以当作属性去使用(装饰器方式,类属性方式)

  • 用法,一般把私有属性设置为property属性,这样形式上私有属性可以作为普通属性使用,但实际是受到保护的私有属性。
  • 装饰器方式
# 1 快速访问私有属性
class Person(object):
    def __init__(self):
        self.__age=0
    @property       #【property属性,该属性的名字和下面方法的名字一样】 
    def age(self):
        return self.__age
p=Person()
print(p.age)

# 2 修改property属性
class Person(object):
    def __init__(self):
        self.__age=0
    @property       #【property属性】
    def age(self):
        return self.__age
    @age.setter
    def age(self,new_age):
        self.__age=new_age
p=Person()
p.age=100
print(p.age)
#【实际上property属性的名字就是被装饰的函数的名字,设置的时候也要用该函数的名字去设置属性】
#【这就产生了一个有趣的现象。我们定义一个私有属性age,却在设置property属性的时候把函数命定义为agee,那么我们的实例化对象要通过 对象名.agee来获得私有属性age。是不是很奇怪!】
#【继续,我们想要修改私有属性age设置的时候,要用property属性的名字.setter设置 因此我们增加装饰器@agee.setter,但我们却把被装饰的修改函数的名字写成了age。那么神奇的事情发生了!,我们需要用agee来获取私有属性age,但是修改的时候却要用age来修改!!】
#【因此我们规定,property属性一定要设置成和要获取的属性相同的名字,修改该属性的时候也要用相同的名字】
  • 类属性方式
# 1 类属性方法设置属性为property属性
class Person(object):
    def __init__(self):
        self.__age=0
    def get_age(self):
        return self.__age
    def set_age(self,new_age):
        self.__age=new_age

    age=property(get_age,set_age) #【注意这里参数的顺序是先get在set,并且传入的是函数名】
p=Person()
p.age=100
print(p.age)
3.3.2with语句和上下文管理器
  • with语句

简单安全的使用

自动关闭文件,异常的时候关闭文件

with在调用方法的时候会先调用上文方法, with语句结束后 或者发生异常 再调用下文方法

# 1 with语句操作文件
with open('test.txt',"r") as f:
    file_data=f.read()
    print(file_data)
  • 上下文管理器

管理某些操作所需要的前提操作,和必要的后续操作

  • 定义上下文管理器

类中由enter和exit方法的对象,就是上下文管理器

with修饰可以在使用方法的时候执行上文方法,并且自动执行下文方法

open方法是一个上下文管理器,因此with修饰后才可以做到自动关闭文件

# 1 上下文管理器 【模拟实现open()方法,上下文管理器】
class File(object):

    def __init__(self,file_name,file_model):
        self.file_name=file_name
        self.file_model=file_model

    def __enter__(self):
        print("进入上文方法")
        self.file=open(self.file_name,self.file_model)
        return self.file
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("进入下文方法")
        self.file.close()

with File("test.txt","r") as f:
    print(f.read())
3.3.3生成器的创建方式

根据设计者指定的规则,循环生成数据,当条件不在成立时,不再生成数据

数据不是一次性全部生成出来的,而是使用一个再生成一个,可以节约大量 【内存】

  • 生成器的使用场景介绍,

比如我们使用列表推导式生成了100个数据,t1时间我们需要10个,此时由100个数据,t2时间我们需要20个此时有20个数据,t3时间我们需要100个,此时有100个数据。如果我们可以根据使用的情况自动生成相应的数据,t1有10个,t2的时候再生成10个,t3的时候再生成80个,这样是不是就节省空间了?

【注意: 获取的值只能顺序获取 无法做到随机取值】

# 1 生成器推导式创建推导式
my_list=(i for i in range(100))
next(my_list)  #next(生成器名字)获取一个数据【按照顺序一个一个获取】

# 2 yield关键字 在函数内部生成数据
def mygenerater(n):
    for i in range(n):
        print('开始生成...')
        yield i  #【暂停(状态保存)并且把i返回】【下次启动时在暂停位置重新开始】
        print('完成一次')  
    #【for循环在生成完后会自动抛出异常,处理异常】
for i in mygenerater(10)
	print(i)   #【for循环 这种方法在使用完后不会产生异常】
    
    
# 3 实例,生成斐波那契数列
def fb(num):
    a=0
    b=1
    #记录生成了几个数字
    index=0
    while index<num :
        result=a
        a,b=b,a+b   #a是当前位置上的数,b是下个位置的数
        index +=1
        yield result

for i in fb(10):
    print(i)
3.3.4深拷贝和浅拷贝
  • 浅拷贝

copy函数是浅拷贝,只对可变类型的第一层对象进行拷贝

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hywPMTY4-1681201977314)(python基础和第三方库.assets/image-20230411152124866.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xavALWQl-1681201977315)(python基础和第三方库.assets/image-20230411152401580.png)]

# 1 浅拷贝例子
import copy
a=[1,2,3]
b=[11,22,33]
c=[a,b]
d=c
e=copy.copy(c)
print(id(d))
print(id(c))
print(id(e))
#【可以看到 dc一样e和他们不一样】
print(id(a))
print(id(d[0]))
print(id(c[0]))
print(id(e[0]))
#【可以看到全都一样,也就是说内层数据都是指向同一块空间的】

# 2 浅拷贝不可变数据类型 直接引用,不会开辟新的空间
  • 深拷贝

拷贝,所有都拷贝

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1VcXyCwW-1681201977316)(python基础和第三方库.assets/image-20230411153415683.png)]

# 1 深拷贝例子
import copy
a=[1,2,3]
b=[11,22,33]
c=[a,b]
e=copy.deepcopy(c)
print(id(c[0]))
print(id(e[0]))
#【上面的结果是不同的】

# 1 深拷贝 不可变类型 同浅拷贝一样,不开辟任何空间,是一个引用

3.4正则表达式

基于文本规则的代码

0\d{2}-\d{8}这是一个正则表达式,匹配的是一个以0开头加两个数字加一个-再加8个数字的字符串 例如012-12345678

  • python中使用正则表达式
# 1 re模块
import re
result = re.match(正则表达式,要匹配的字符串)   #【匹配到是一个结果,没匹配到是None】
result.group()  #获取匹配好的字符串
  • re匹配单个字符
代码功能
.匹配任意一个字符
【】匹配【】中的字符
\d数字
\D匹配非数字
\s匹配空格 tab键
\S匹配非空白
\w匹配非特殊字符 a-z A-z 0-9 _ 汉字
\W匹配特殊字符 *±/!,。
import re

result = re.match("itcast.", 'itcast1')    
result = re.match("itcast[1234abcd]", 'itcasty')  #【注意[]中没有逗号】
result = re.match("itcast[0-9]", 'itcasty')  #【匹配0-9】
info = result.group()
print(info)
  • 匹配多个字符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gv95dIq0-1681201977317)(python基础和第三方库.assets/image-20230411155659760.png)]

  • 匹配开头和结尾

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IXxZRkP9-1681201977318)(python基础和第三方库.assets/image-20230411155957464.png)]

result = re.match("^\d*\w*", '1324adsfdsa')   #【以任意多个数字为开头,之后跟着任意多个常规符号】
result = re.match("^\d*\w*\d$", '1324adsfdsa')  #【必须以数字为结尾,\d$】
result = re.match("^d.*[^4]$", '1324adsfdsa')  #【必须以数字为结尾,\d$】
  • ⭐匹配分组

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DnHmABHd-1681201977318)(python基础和第三方库.assets/image-20230411160824715.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PdHSZymm-1681201977319)(python基础和第三方库.assets/image-20230411160923962.png)]

# 1 【匹配多个确定的序列】 
import re
fruit=["apple",'banana',"orange","pear"]
for i in fruit:
    result = re.match("apple|pear|orange", i)  
    if result:
        info = result.group()
        print(info)
        
# 2 【|多与()一起用在()中选择】
result = re.match("[a-zA-Z0-9_]{4,20}@(163|qq|126).com", "hello@163.com")  
if result:
    info = result.group()
    print(info)
    
# 3 
result = re.match("(qq):([1-9]\d{4,11})", "qq:12345")  
if result:
    info = result.group(1)  #【group中的参数代表的是第几个分组 ,分组从1开始】
    info = result.group(2)
    print(info)

# 4 
result = re.match("<([a-zA-Z1-6]{3,4})>(.*)(</\\1>)", "<html>hh</html>")  #【注意\\1】
if result:
    info = result.group()
    print(info)

# 5  【多分组】
result = re.match("<([a-zA-Z1-6]{4})><([a-zA-Z1-6]{2})>.*</\\2></\\1>", "<html><h1>hh</h1></html>")  
if result:
    info = result.group()
    print(info)

# 6 【分组别名】 
result = re.match("<(?P<html>[a-zA-Z1-6]{4})><(?P<h1>[a-zA-Z1-6]{2})>.*</(?P=h1)></(?P=html)>", "<html><h1>hh</h1></html>")
if result:
    info = result.group()
    print(info)

第三方库

数据分析三大件NPM

Numpy

数值计算库,里面有一些自己的数据结构

import numpy as np
  • np相关数据的属性
t1=np.array(list)
t1.dtyp  #求属性,t1的类型
t1.shape    #属性,形状  是一个元组
t1.T
数组相关
  • 创建
#创建一个数组
t1=np.array(list1)
t2=np.array(range(n))
t3=np.arange(10)   #和range类似,自动生成0到9之间的np.array类型的数组

#创建全为0/1的数组
t1=np.zeros((a,b))  #创建a行b列的一个全为0的数组
t1=np.ones((a,b))  #创建a行b列的一个全为1的数组

#创建一个主对角线全为1的方阵
t1=np.eye(3)  #3X3的
  • 数组类型
#数据类型
t4=np.array(range(n),dtype='int64')  #dtype指定数据的类型
t4.astype("float32")  #astype()是调整数据类型
  • 保留几位小数
#数据精度操作
t5=np.array([random.random() for i in range(10)])  #生成一些小数
t6=np.round(t5,2)  #t6为t5中每个数字取两位小数后的结果
  • 数组维数相关
# 1 二维数组,以2行为例子
t4=np.array([list1,list2])
# 2 三维数组
(a,b,c)  #a表示数据块数,b,c表示每块里面的二维行列数
# 3 修改形状  注意reshape不会改变原数组
t1.reshape((3,4))  #改成3行四列的二维数组 【不修改元数据】
# 4 展开
t1.flatten() #【不修改元数据】

  • 数组相关计算
t1=np.array(list)
# 1 数组加一个数
t2=t1+5   #t1中每个数据都+5  同理-*/也一样
t2=t1/0   #? 结果是一个同为数组,由nan和inf组成,nan表示不是一个数,inf表示无穷 其中0/0=nan  非0/0=inf

# 2 两个同维度数组计算
t2=t1+t1  #两个数组形状相同  对应位置相加—*/同理 

#3 n*m-1*m /n*m-n*1   【结果是n*m中每行的列都减去1*m中对应列的元素/后者同理。同理-*/也一样】

# 4 数组的布尔运算
t1<10   #得到的是同纬度数据,每个数据小于10为true大于10为false

# 5 数组的转置
t1.T  #这是一个属性,【不改变原来的数据】

  • 数组的分割(索引和切片)和组合
# 1 取数组中一个数或者某行某列
t1=np.array(list)
t2=t1[1][1]  #取一行一列的数据,注意行列从0开始排序  【结果是np.int类型或者np.float类型】
t2=t1[1,1]  #【和第三行代码结果相同】
t2=t1[1]  #t1的一行  【是一维数组】
 
# 2 取多行或者多列   【返回的是二维数组】
t1[2:5,0:2]  #(连续)2到5行,0到2列数据
t1[[1,2,5],0:2]  #(离散)1,2,5行的0到2列数据  

# 3 取不连续的一些点的数据 【返回的是一维数组】
t1[[1,3,4],[1,5,4]]  #取(1,2),(3,5),(4,4)列这三个数据

# 4 bool索引
t1[t1>10]   #找到数据小于10的数 【返回一个一维数组】

# 5 数组的拼接
np.vstack((t1,t2))  #竖直拼接,同列数
np.hstack((t1,t2))  #水平拼接,同行数

# 6 条件取值
temp[条件]  #取条件成立情况下的值
  • 数值的修改
# 1 首先通过索引切片找到要修改的数据,然后修改即可

# 2 条件修改
t1[t1<10]=1  #修改数组中比10小的数字为1

# 3 三目运算符修改
np.where(t1<=10,0,10)  #t1中小于等于10的为0 其他的为10  【会修改原数据】

# 4 clip裁剪操作
t1.clip(10,18)  #小于10的替换成10,大于18的替换成18

# 5 nan赋值
t1[2,3]=np.nan  #t1的(2,3)数据修改为nan

# 6 交换数组的某行某列
t[[1,2]:]=t[[2,1],:]  #t交换一行一列  【会修改原数据】
  • 数组的copy和view
# 1 numpy的引用
a=b #是一个引用,互相影响但不会创建新的对象
# 2 copy
a=b.copy()  #复制一份
# 3 view
a=b[:]   #试图操作,会创建新的对象a,a与b的数据变化是一致的
numpy里一些函数
# 1 最值函数
np.argmax(t,axix=0)  #求0轴方向上的最大值的index,即求每一列的最大值索引【返回的是一个一维数组】
np.argmin(t,axis=1)
np.max()
t.max()   #求最大值
t.min()

# 2 生成随机数
np.random.rand(2,3)  #随机生成2行3列的数组 【取值为0-1,符合均匀分布】【float】
np.random.randn(2,3)  #随机生成2行3列的数组 【取值为0-1,符合正太分布,均值为0,方差为1】【float】

np.random.randint(low,high,(a,b))  #随机生成a行b列的数组 【取值为low-high,符合均匀分布】【int】
np.random.nuiform(low,high,(a,b))  #随机生成a行b列的数组 【取值为low-high,符合均匀分布】【float】
np.random.normal(loc,scale,(a,b))  #随机生成a行b列的数组 【取值为low-high,符合正太分布,均值为loc,方差为scale】【float】

np.random.seed(10)  #确定随机数种子之后每次生成的随机数一模一样,再程序测试阶段使用        

# 3 求两个数组中不相同元素的个数
np.count_nonzero()  #求数组里面不为零的数的个数
np.count_nonzero(t1!=t2)  #求t1中对应位置元素和t2相同的个数 【同维度,t1如果不等于t1就为1】  

#下列统计函数无论使用np.  还是数组名.都可以
# 4 求和函数
np.sum(t1)  #求所有元素的和
t.sum()
np.sum(t3,axis=0)   #所有列相加的结果【返回一个一维数组】

np.mean()  #平均值
np.median()  #中位数
np.ptp()  #极值
np.std()  #标准差
Nan 与 Inf
  • nan与inf都是float
  • nan和任何元素运算都为nan
# 1 nan是不相等的
# 2 判断nan的个数
np.count_nonzero(t!=t)
np.isnan(t2)   #如果是nan则为true
轴的概念

后续对数组的各种操作都建立在轴上

shape(a,b,c) a是0轴 b是1轴 c是2轴 不同维度的数据轴的排列是不一样的

二维数组 行方向是0轴,列方向是1轴

三维数组 块方向是0轴,行方向是1轴,列方向是2轴

Pandas

基于numpy实现的更具类

可以处理数值之外的而数据,包括字符串,时间序列等

#属性Series
dtype  #对象属性,返回对象里面数据的类型
index  #索引
values  #values   【返回的是一个数组】
ndim   #数据维度
pandas(Series)
# 1 数据类型
Series    #一维带标签的数组  值得就是索引
DataFrame  #二维  Series容器

# 2 指定索引  【关于索引,如果传入的是字典,a,a和索引能对应起来的则取值,如果索引里面有a里面没有取NAN,如果a里面有索引里面没有则忽略该值】
pd.Series([1,2,3,4],index='abcd')

# 3 通过字典创建Series
dic={
    'a':1,
    'b':2,
    'c':3,
}
a=pd.Series(dic)

# 4 修改数据类型
a.astype(float)  #同numpy操作类似

# 5 取值  
a['a']  #索引来取
a[0]   #位置取值
a[[1,2,3,4]]
a[:3]
a[['a','b','c']]   #如果没有这个索引取到的是nan
t[t>4]    

# 6 to_list
a.to_list   #把Series转换为列表
读取文件
# 1 读取csv
df=pd.read_csv('filepath')  #【结果是一个FrameDate类型数据】
panda(DateFrame)

有一个index索引行索引,和一个columns列索引,代表的是列属性 默认从0开始增加

# 1 创建DateFrame 
pd.DataFrame(np.arrange(12).reshape(3,4),index=list('abc'),columns=list('ABCD'))   #【接收的参数是一个二维数组】

# 2 根据字典/列表创建DateFrame
a={
    'name':['1','2'],
    'age':[18,20],
    'tel':[100,120]
}  
b=[{'name':'1','age':18,'tel':100},{'name':'2','age':20,'tel':120}]
pd.DateFrame(a)   #【注意字典的格式,values是列表】
pd.DateFrame(b)   #【注意列表的格式,元素是字典】

# 3 数据显示方法
df.head(5)    #头部5行
df.tail(5)  #尾部5行
df.info()   #相关信息,行列数,非空值个数,列类型,内存占用
df.describe()  #统计结果:计数,均值,标准差等等等  【只有数值列才可以计算】

# 4 排序方法
dp.sort_values(by='列名',ascending=False) #根据某一列排序  #ascending默认为true递增排序

# 5 取值
df['列名']  #取具体某一列   【返回值是Series】
df[0]['列名']  #取某个数据
df[:20]  #取前20行
df.iloc[:20,:20]   #和其他数据类型的取行列效果一样【注意要用iloc方法来取】  【通过位置获取】
df.loc[['a','b'],['A','B']]  #和iloc效果类似      【通过行列索引名字取值】
df.loc['a':'f',['w','z']]   #连续取行,【注意af都被选中】

# 6 布尔索引
df[df['a']>800]  #取df的a列中大于800的数据
df[(df['a']>800)&(df['a']<1000)]   #多个索引条件需要用&链接

# 7 DateFrame里面的字符串
da['A'].str.len()   #求da的A列里面的每个元素的len【注意要用str.len()才能让len作用到每一行】

# 8 数据插入
data.insert(0,'ones',1,axis=1)数据插入,插入到第零列,起名字为ones,用1填充
数据缺失处理
# 1 判断nan
pd.iana(df)
pd.notna(df)
df.isna()  #返回的结果都是布尔类型

# 2 删除nan
df.dropna(axis=0)  #找到nan按照行删除
df.dropna(axis=0,how='all')  #找到nan按照行删除  【只有某行全部为nan才删除】
df.dropna(axis=0,how='all',inplace=True)  #【原地修改该变量】

# 3 填充nan
df.fillna(100)  #填充100给nan
df.fillna(df.mean())  #自动根据某列的平均值来帮助我们填充该列nan
统计方法和字符串离散化(案例)
  • 统计方法
# !!注意,DateFrame利用统计方法默认是作用与每一列

# 1 把某列变成一个列表,其中每个元素只出现依次
df['Director'].unique()   #【输出是一个列表】

# 2 列表里面还是列表 转换为一个单列表
a=np.array([1,2,3],[4,5,6])
b=a.flatten()  #【1,2,3,4,5,6】
a=[[1,2,3],[4,5]]  #列表里面的列表长度不相同
b=[i for j in a for i in j]  #【1,2,3,4,5】

# 3 统计方法  可以获取某一列后进行统计计算
df['列明'].mean()
df['列明'].min()
df['列明'].median()
df['列明'].argmax()
  • 字符串离散化案例
# 1 案例 
temp_list=df['Category'].str.split(',').tolist()  #先把Category里面的每个电影的类型字符串分割,然后合并成一个[[],[],[]]
category_list=(list(set([i for j in temp_list for i in j])))   #把一个[[],[],[]]=>[] 并且通过set去重
zeros_list=pd.DataFrame(np.zeros((df.shape[0],len(temp_list))),columns=temp_list)  #创建一个全为0的数组,行为数据的行,列为所有类型的列
#给每个电影出现分类的位置复制为1
for i in range(df.shape[0]):
    zeros_list.loc[i,temp_list[i]]=1  

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8I5wvM9u-1681201977319)(python基础和第三方库.assets/image-20230408145034374.png)]

数据合并和分组聚合
  • 数据合并
# 1 水平拼接 (左右拼接)
t1.join(t2)  #以t1的行为基准,没有的数据用nan 

# 2 条件合并  (左右合并)
t1.merge(t2,on='a')  #笛卡尔积操作,但是只有t1,t2中a列数据相同的行进行笛卡尔积
  • 数据分组聚合
# 1 分组 【按照某一列的不同值进行】【分组后的结果实际上就是index和values】
group=df.groupby(by='列名')   
for i,j in group:
    print(i,j)  #i是该列的值,j是该列为i值的DataFrame对象
    
# 2 聚合方法
group.count()  #统计按照某列分组后,不同的分组中其他列包含多少条数据
group.mean()    #统计按照某列分组后,不同的分组中其他列数据的平均值

# 3 对多列进行分类,并且只求分类后数据某一列的count值
group=df['Brand'].groupby(by=[df['country'],df['province']])
print(group)
group=df[['Brand']].groupby(by=[df['country'],df['province']])  #两个[[]]结果是DateFrame
  • 关于索引
# 1 以某列数据作为索引
df.set_index('列名',drop=False)  #【drop=False该列不会被删除,不会改变df原来的索引】
df.set_index(['列名1','列名2'])  #【多索引】

#注意Series可以直接用ad['索引名字']来取值,但是DateFrame需要用ad.loc['索引名字']来取值
时间序列
# 1 生成一段时间范围
pd.data_range(start=None,end=None,Periods=None,freq='D')  #periods代表生成几个时间
pd.date_range(start='20171230',end='20180131',freq='10D')  #生成一段时间,按照10天间隔十个昵称

# 2 把字符串转化为格式化时间类型
pd.to_datetime('字符串',format='')  #format告诉程序用什么样的程序进行格式化操作

# 3 时间重采样
t.resample('M').mean()  #t是一个时间类型,按照月份进行重采样 并且求平均值

# 4 时间格式化
t.strftime("%Y-%m-%d")  #t是一个时间格式的变量,strftime进行时间格式化

matplotlib

数据画图工具

散点图,直方图,柱状图

可以去官网查看不同的图形代码样例,改一下就可以

#修改matplotlib字体 
matplotlib.rc()  
折线图

plot()绘制折线图

  • 简单绘制折线图
from matplotlib import pyplot as plt  #导入包
x=range(2,26,2)   #折线图x轴
y=[15,13,14,17,20,25,26,26,24,22,18,15]   #折线图y轴
plt.plot(x,y)
plt.show()
#其中xy轴的刻度是根据给定的数据自动生成的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rzwle70y-1681201977319)(python基础和第三方库.assets/image-20230405105404192.png)]

  • 完善X轴刻度显示
import matplotlib.pyplot as plt
#画图前修改图片大小dpi等属性信息
plt.figure(figsize=(20,8),dpi=80)  
#数据配置
x=range(2,26,2)   
y=[15,13,14,17,20,25,26,26,24,22,18,15]   
#绘图
plt.plot(x,y)

# !!设置x轴相关
#设置x轴的刻度  
plt.xticks(x)   #用x列表里面的值设置x轴的刻度
plt.yticks(range(min(y)-2,max(y)+2))
#设置x轴的刻度为字符串
plt.xticks(x,_str)  #x和_str一一对应,不显示x里面的值,而是显示对应的在_str里面的值 注意x与_str中的元素个数要相同
#旋转90度 ratationx轴标记旋转90度
plt.xticks(x,_str,rotation=90)
#设置X轴字体为中文
my_front = font_manager.FontProperties(fname="字体路径")
plt.xticks(_x,_str,fontproperties=my_front)

#保存图片,可以保存为svg或者png
plt.savefig("./t1.svg")
plt.show()
  • 添加总体描述信息,x轴y轴以及图的含义
plt.xlabel("时间")
plt.ylabel("温度")
plt.title("时间温度情况")
  • 网格线
plt.grid(alpha=0.4)  #根据x轴和y轴的刻度绘制网格 alpha为透明度
  • 多个曲线如何区别(添加图例)
#为曲线添加名字
plt.plot(x1,y1,label='a')
plt.plot(x2,y2,label='b')

#添加标签,即曲线名字  如果要使用中文 关键字为prop
plt.legend(prop=my_font)

#显示在左上角
plt.legend(prop=my_font,loc="upper left")
  • 自己设置线条颜色形状
#橙色和虚线,点表示  #color也可以用16进制颜色代码,记得前面加#
plt.plot(x,y,label='self',color='orange',linestyle=':')
plt.plot(x,y,label='self',color='orange',linestyle='--')

#设置网格形状
plt.grid(alpha=0.4,linesytle='--')
绘制散点图
#plt.scatter()绘制即可,其他的描述语言和折线图一样
plt.scatter(x,y)   #xy是列表
绘制条形图
#plt.bar()
plt.bar(x,y,width=0.3)    #xy是列表  width修改条状图的宽度
#横着绘制   
plt.barh(x,y,height)       #注意这里的xy不变,x还是自变量,y还是因变量 但是在后面plt.xtick的时候因为x轴和y轴反转了,因此需要修改
#绘制多个条形图
#和其他图形多次绘制相同,不过需要注意的是不同图形的x轴要偏移一点
import matplotlib.pyplot as plt

x=['test1','test2','test3','test4','test5']
y1=[203,231,45,73,123]
y2=[123,55,62,724,212]
y3=[123,356,21,41,612]

width=0.2
x1=[i for i in range(5)]
x2=[i+width for i in range(5)]
x3=[i+ width*2 for i in range(5)]
plt.bar(x1,y1,width=width,label='x1')
plt.bar(x2,y2,width=width,label='x2')
plt.bar(x3,y3,width=width,label='x3')
plt.legend()
plt.xticks(x2,x)
plt.xlabel('X')
plt.ylabel('Y',rotation=90)
plt.title('test')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-akY6jikQ-1681201977320)(python基础和第三方库.assets/image-20230406102609010.png)]

绘制直方图

和条形图的区别就是 x轴连续

import matplotlib.pyplot as plt
import random
#随机300个数,求从0到100步长为10之间的数的个数,比如0-10之间的个数,10-20之间的个数 其中区间是[a,b)
y1=[random.randint(0,100) for i in range(300)
x1=[i for i in range(0,101,10)]
plt.hist(y1,x1) #其中y1是原始数据,x1是我们设置的值,该直方图用于统计y1中落在x1中相邻两个数之间的个数
plt.xticks(x1)
plt.grid()
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jbAUJ2jy-1681201977326)(python基础和第三方库.assets/image-20230406110009373.png)]

⭐其他图形

matplotlib其他图形网站

http://matplotlib.org/gallery/index.html

关于前端交互式绘图可以参考如下网站,通过numpy和pandas把数据处理好传送过去即可

Apache ECharts

plotly 画图界的GitHub

https://plot.ly/python/

其他常用库

random

#随机数x   a<=x<=b
random.ranint(a,b)
abs()  #绝对值函数
round()  #四舍五入函数

conda相关命令

  • conda install [package name]

  • conda activate [环境名]

  • conda deactivate #退出虚拟环境

pandas/numpy/matlib

读文件数据处理相关

data = pd.read_csv('ex1data1.txt',names=['population','profit'])
第一个参数是文件名,并且在当前文件目录下,第二个参数names给文件的列起名字  返回值是dataframe类型

data.head()
data.tail()    打印出data的后几行

data.describe() #数据信息统计

data.info() #数据结构信息

reg=np.insert(reg,0,values=0,axis=0)在第零行插入一个值values 行插入用axis=0 reg为被插入的数据
 
data.iloc[:,0:-1]数据切片 默认有逗号隔开,从0列开始一直到倒数第一列之前的(不包括倒数第一列)

np.array(x) 把dataframele类型转换为数组类型(矩阵)

X.shape 看看x是什么样的矩阵

Y.reshape(n,m)把y重塑成N x M型的矩阵

X@Y 矩阵乘法

X*Y 矩阵点乘,表示矩阵对应元素相乘,型不变
np.zeros((2,1))初始化一个2行一列的矩阵,默认值为0

cost.append(cos) cost数组后面添加一个元素cos

x=np.linspace(0,25,100) 生成一个以为列表 最小值为0最大值为25 一共100个数

acc=np.mean(y_pre==Y)  y_pre==y为1否则为零,之后求平均值

映射函数,把线性映射到非线性 其中power是最大的次数

def feature_mapping(x1,x2,power):
    data ={}   #定义一个字典用来存储映射后的数据
    for i in np.arange(power+1):
        for j in np.arange(i+1):
            data['F{}{}'.format(i-j,j)]=np.power(x1,i-j)*np.power(x2,j)
    
    return pd.DataFrame(data)  #把字典变成dataframe类型的数据
tpye(data)    data的类型
data['X']  获取X值的字典

绘图相关

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IGasSrPB-1681201977326)(C:\Users\顾子茵\AppData\Roaming\Typora\typora-user-images\image-20230228144924039.png)]

fig,ax=plt.subplots(a,b)  绘图实例ax其中有a X b个图,无参默认一个图

ax.plot(a,b,label='') 绘制曲线图,横坐标数为a,纵坐标数为b其中a b都是一维数组 label 表示绘制的该条曲线的标签


ax.scatter(a,b,label='') 散点图,其中 a,b为列表
plt.scatter(X[:,0],X[:,1],c=Y.flatten(),cmap='jet')   #根据Y值的不同绘制颜色不同的点
ax.legend()  如label无法显示出来就加上一句

ax.set(xlable='',ylabel='',title='')x轴的名字 y轴的名字 图的名字

ax.scatter(data[data['accepted']==0]['exam1'],data[data['accepted']==0]['exam2'],c='r',marker='x',label='y=0')
#data[data[iaccepted]==0]['exam1']取出data中所有accepted==0的exam1列数据为x轴数据,同理为y轴数据,marker='x' 用x表示该点

等高线画法

登高线图画法

x=np.linspace(-1.2,1.2,200)##均匀分布的数组,-1.2到1.2之间
xx,yy=np.meshgrid(x,x)  生成与x行 与y列对应 的二维矩阵
z=feature_mapping(xx.ravel(),yy.ravel(),6).values   xx.ravel()把二维矩阵变成向量    xx.flatten()表示把行向量或者列向量变成一维数组的形式。

zz=z@theta_final
zz=zz.reshape(xx.shape)  

plt.contour(xx,yy,zz,0)    话等高线,其中0表示只画出zz为0的等高线

决策边界

def plot_boundary(model):
    x_min,x_max=-0.5,4.5
    y_min,y_max=1.3,5
    xx,yy=np.meshgrid(np.linspace(x_min,x_max,500),np.linspace(y_min,y_max,500))
    z=model.predict(np.c_[xx.flatten(),yy.flatten()])
    
    zz=z.reshape(xx.shape)
    plt.contour(xx,yy,zz)

svm包

svc1=SVC(C=1,kernel='linear/rbf', gamma=gamma)   #获取一个svc模型实例,传入相应的c值选择对应的核函数gamma是和函数里的方差
svc1.fit(X,Y.flatten())  #x是矩阵,返回一个一维数组,比如吧n行1列的列向量变成一个一维数组
svc1.predict(X)  #输入矩阵后输出对应的预测结果
svc1.score(X,Y.flatten)   #获取该模型的精确度



ray

ray.get 获取到的值为(array([]),2,3,‘stirng’)时如何获取array或者string

以上述例子
result=ray.get(work1_id)[1]   结果是2
result=ray.get(work1_id)[3]   结果是string

string

# 1 返回第n个字母 从a到z
a=string.ascii_uppercase[5]  #【返回第五个字母大写的E】
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值