【从0开始入门python】一个半月的三万字学习笔记汇总!!!

禹昆
2023-12-01
  • python学习

    • DAY01-DAY04基础操作
    • DAY05-DAY09基本模块

    常用pip源

    (1)阿里云

    http://mirrors.aliyun.com/pypi/simple/
    

    (2)豆瓣

    http://pypi.douban.com/simple/
    

    (3)清华大学

    https://pypi.tuna.tsinghua.edu.cn/simple/
    

    (4)中国科学技术大学

    http://pypi.mirrors.ustc.edu.cn/simple/
    

    (5)华中科技大学

     http://pypi.hustunique.com/
    

第一讲

基础知识

# ctrl+/ 添加注释
# ctrl+alt+l 三键实现格式规范
# 或者在pycharm编译器中点击“code->Reformat Code
# 英文输入符号
# \+特定字符 产生一个新的含义,就是转义字符(# \\ \t)
print(666)
print('我爱编程')
# sep=','指定,为分隔变量的符号
print('唐三', '小舞', '张三', sep=',')
print('唐三', '小舞', sep='\n')
# end='\n'指定换行结尾
print('唐三', '小舞', end='*')
print('唐三', '小舞', end='\n')
# 变量
# 1.有一定意义
# 2.由数字,字母,下划线组成,数字不能开头
name = '张三'#等号是赋值
print(name)
# input()表示输入,在括号里面加入''可加入提示
input('请输入您的密码')

第二讲

数据类型

# 整型 int
# 浮点型 float
# 字符型 str
# '''中间可以放几段话'''
name = '''
啦啦啦
啦啦啦
啦啦啦
'''
print(name)
# type函数
name = '漩涡鸣人'
print(type(name))
# 运算注意优先级以及从左向右计算
# 字符不能和整数类型相加,但可以变换
name = '张三'
age = 48
print(name + str(age))
# 同理整型和浮点类型也可以相互转换,但有非数字的字符不能转换为整数,也不能是浮点类型结构

第三讲

运算符

# + - * / % 加减乘除求余
number = input('请输入数字')
number = int(number) # 输入的是字符类型,用int转换为整数类型进行运算
result = number % 2
print(result)
# //表示整除运算
bounty = 5000
print(bounty/280) # 结果是17.86
print(bounty//280) # 结果是17
# += *= /= -= 运算符
# 关系运算符返回值类型是布尔类型
# ord()函数可以查看字符对应的整数数值
print(ord('a'))
# 逻辑运算符 and or not
# and 有假就为假   or 有真就为真  not 真就假假就真

第四讲

条件语句

  1. if语句的使用
  2. if…else语句的使用
  3. 多重if语句的使用
  4. if嵌套
# if 要判断的条件:        (标准结构)
#     条件成立时要做的事情
# else:
#     条件成立时要做的事情
money = input('请输入您的钱数')
money = int(money) # 注意转换
things1 = '盲盒'
if money>35:
   print('拿下{}'.format(things1))
# 用{}进行占位,用.format()函数填充占位
else:
   print('买不起')
# elif语句
# if 条件1:
#     事情1
# elif 条件2:
#     事情2
# else:
#     事情3
choice1 = input('请输入你要选的品牌')
choice2 = input('请输入你要选的衣服类型')
money = input('请输入你手中有多少钱')
money = int(money)
if choice1 == '安踏' and choice2 == '短袖' and money > 60 :
    print('您购买了{}品牌的{}'.format(choice1,choice2), '您还有{}元钱'.format(money-60) , sep = '\n')
elif choice1 == '李宁' and choice2 == '短袖' and money > 60 :
    print('您购买了{}品牌的{}'.format(choice1,choice2), '您还有{}元钱'.format(money-60) , sep = '\n')
elif choice1 == '耐克' and choice2 == '短袖' and money > 60:
    print('您购买了{}品牌的{}'.format(choice1, choice2), '您还有{}元钱'.format(money - 60), sep='\n')
else:
    print('您要的我们没有或者您的钱不足以支付请重试')
    # if下语句可继续嵌套if

第五讲

循环语句

  1. while的使用
  2. for的使用
  3. break和continue的使用
  4. while或者for与else结合使用

循环的核心在于减少重复代码,条件要尽量通用化

# while 循环条件:(当循环条件不成立时结束)
# 	循环执行的代码
i = input('请输入数字')
i = int(i)
while i <= 5:
    i += 1
    print(i)
# 需求:限制登陆次数
i = 3
while i >= 1:
    username = input('请输入用户名')
    password = input('请输入密码')
    if username == 'admin' and password == '123456' :
        print('登录成功')
        break # 作用在于登录成功后退出循环
    else:
        print('登录失败')
        i -= 1
        print('还有{}次机会' .format(i))
        continue # 继续循环
# for 变量 in 序列:
#		循环体
# 变量:自定义变量名,要求和单独定义时候一样
# 序列:容器型数据类型的数据,比如字符串,布尔,列表,元组,集合
# 循环体:需要重复执行的代码
for x in range(1,11):
    print('今天你直播下单{}次'.format(x))
    # range()函数作用是产生一个序列,从0开始
    # range(1,11)则表示从1开始11结束但是不包括11
    # range(1,6,2)表示135的序列,即2为步长(可以是负数)
# 需求:限制登陆次数
for i in range(3):
    username = input('请输入用户名')
    password = input('请输入密码')
    if username == 'admin' and password == '123456' :
        print('登录成功')
        break # 作用在于登录成功后退出循环
    else:
        print('登录失败')
        print('还有{}次机会' .format(2-i))
        continue # 继续循环
# continue 跳过本次循环,后面语句不执行,继续执行下一次循环
# 需求:打印1-12数字,除了8不打印
# 方法一
for i in range(1,13):
    if i == 8:
        continue
    else:
        print(i)
# 方法二
i = 1
while i <12:
    i += 1
    if i == 8 :
        continue
    print(i)
# else可以和while,for进行配合
# 案例一
i = 13
while i <12:
    print('验证失败')
else:
    print('验证成功')
# 案例二
for i in range(8):
    print(i , end=' ')
else:
    print('\n')
    print('结束')

第六讲

数据类型列表(列表类似数组,字典类似结构体)

  1. 列表的使用
  2. 字典的使用
  3. 字符串的使用
# 以前介绍的int bool str float都只能存放一个值,需要列表存放一堆值
# 变量名字 = [元素,元素,元素]
heros = ['张三', '张四', '张五', '张六', '张七', '张八']
print(type(heros))

输出结果是<class ‘list’>,即构成了一种新的数据类型列表

# 那怎么找到列表中的某一个元素呢?这就要用到列表索引
# 计算机编号从0开始,相关方式类比数组
heros = ['张三', '张四', '张五', '张六', '张七', '张八']
print(heros[1])

即可获取张四,同理可以获取其他元素,若要同时获取多个元素,则要使用列表切片的办法

# 1:3表示索引的一个左闭右开区间,只包含左边不包含右边
heros = ['张三', '张四', '张五', '张六', '张七', '张八']
print(heros[0:6])
# [3:]若省去终止位置,则表示从标明的初始位置一直索引到终止位置
heros = ['张三', '张四', '张五', '张六', '张七', '张八']
print(heros[0:])

这样就可以把上述元素全部输出出来了(俩个方法结果一样)

输出结果为 [‘张三’, ‘张四’, ‘张五’, ‘张六’, ‘张七’, ‘张八’]

但是显然不可能所有的取法步长都为一也不可能都是顺序取元素

# 完整格式  print(列表名(初始位置:终止位置:步长)) 默认步长为+1
heros = ['张三', '张四', '张五', '张六', '张七', '张八']
print(heros[0::2])

这样就可以输出从第一个元素开始的所有奇数项元素

我们在长数据超大数据时,往往不方便一次看出到底有多少个元素

# len()函数可以获取列表的长度
print(len(heros))

我们往往需要增加删除修改查找列表元素,实现列表元素动态管理

(增删改查)

增
# append可以实现列表元素增加
heros.append('张九')
# insert函数可以定向添加元素
# insert方法只是插入元素,原来在此位置以及之后的元素全体后移
heros.insert(3, '张六plus')

删
# pop或者remove可以实现列表元素删除
# 列表.pop[索引]表示删除特定位置索引位置的元素
heros.pop() # 若索引为空表示删除最后一个元素
heros.remove('张三') # 移除张三这个元素

改
heros[0] = '张三plus' # 实现修改定向位置的元素

查
# index函数可以实现查找某一元素具体位置,并通过变量存储,在案例实现的时候有奇效
number1 = heros.index('张三')
print(number1)
# 可以利用 in 来判断元素在不在列表内
# 格式  查找的元素 in 列表名  返回值是布尔类型,可以用int转换后用变量储存下来
heros = ['张三', '张四', '张五', '张六', '张七', '张八']
number3 = int('张2' in heros)
print(number3)
# index 和 in 可以相互补充相互协调,index返回具体位置,in判断在不在,还可以配合后面的count来判断在不在

有些时候一个列表会有很多重复的元素,我们需要函数来帮我们进行计数

# 列表名.count(要查询的元素)   返回值为元素个数
heros = ['张三', '张四', '张五', '张六', '张七', '张八']
heros.append('张三')
heros.append('张三')
heros.append('张三')
heros.append('张三')
number2 = heros.count('张三')
print(number2)

字典

# 基础格式 变量名字 = {key1:value1,key2:value2}
hero = {'姓名': '孙悟空','性别': '男', '定位':'战士' }
print(hero)
print(type(hero))

得到的结果是<class ‘dict’>即构成了一种新的数据类型列表

字典还可以和列表搭配使用

hero = {'姓名': '孙悟空', '性别': '男', '定位': '战士', '最佳搭档': ['八戒', '沙僧', '唐僧']}
print(hero)
print(type(hero))
# 那如何获取里面中的东西呢
print(hero['性别'])
# 如何判断字典里面是否有我们查找的键呢
# print(字典名.get(查找的键,如果找不到返回的东西))
hero = {'姓名': '孙悟空', '性别': '男', '定位': '战士', '最佳搭档': ['八戒', '沙僧', '唐僧']}
print(hero.get('定位', '未知'))
# 我们用get的时候,如果键存在则返回键的值,如果键不存在则返回设定的返回值,如果我们没有设定返回值,则返回NONE

字典同样支持增删改查操作,实现动态管理

hero = {'姓名': '孙悟空', '性别': '男', '定位': '战士', '最佳搭档': ['八戒', '沙僧', '唐僧']}
hero['血量'] = 4399 # 对于一个原来没有的键进行操作会添加
hero['性别'] = '未知' # 对于一个原来有的键进行操作会修改
print(hero)
# 字典名.pop[键名]表示删除特定键
heros.pop('定位') 
# 可以利用 in 来判断元素在不在字典内
# 格式  查找的键 in 字典  返回值是布尔类型,可以用int转换后用变量储存下来
hero = {'姓名': '孙悟空', '性别': '男', '定位': '战士', '最佳搭档': ['八戒', '沙僧', '唐僧']}
number4 = int('姓名' in hero)
print(number4)
# value函数可以输出字典的所有值
hero = {'姓名': '孙悟空', '性别': '男', '定位': '战士', '最佳搭档': ['八戒', '沙僧', '唐僧']}
print(hero.values())
# 结果为:                                                    dict_values(['孙悟空', '男', '战士', ['八戒', '沙僧', '唐僧']])
# value的作用不光只是显示,还可以配合in进行逻辑判断
hero = {'姓名': '孙悟空', '性别': '男', '定位': '战士', '最佳搭档': ['八戒', '沙僧', '唐僧']}
print(int('孙尚香' in hero.values())) # 返回值为布尔类型

字符串的使用

# 单引号,双引号,三引号三种声明方式,三引号的优点在于可以原样输出,空格空行都会被保留
hero1 = 'hello'
hero2 = "hi"
hero3 =     '''
            hello
            hi
            '''
print(hero1, hero2, hero3)

字符串和列表一样,也有切片和索引的访问形式

把字符串当成字符的列表

message = '王者荣耀'
print(message[0])
print(message[:2]) # 从初始位置到2这个位置
# 案例 在任意一个输入字符串中,查找是否有英雄这个子串
string = input('请输入一个字符串')
lenstr = int(len(string))
for x in range(0, lenstr):
    if string.find('英雄') >= 0:
 # find函数可以查找,如果找到显示第一个字符的位置,如果没找到会返回-1
        print('有英雄这个子串')
        break
    else:
        if x == lenstr - 1 :
            print('没有英雄这个子串')
        else:
            continue
print(string.startswith('王者'))
print(string.endswith('王者'))
# startswitch函数可以判断是否以某某字符或字符串开头,返回值为布尔类型
# endswitch函数可以判断是否以某某字符或字符串结尾,返回值为布尔类型

简化字符串技巧

字符串中有很多空格或者转义字符我们可以用一个函数全部去除

# strip函数
s = '       hello\\\\\mm\n\n\n\n'
print(s.strip())

输出结果是 hello\\mm

第七讲

函数

  1. 函数的作用与定义
  2. 函数的参数
  3. 函数的返回值
# 函数格式(定义)
def sum(num): 
# def关键字表示定义一个函数 sum是函数名 num是形参可以有多个
    result = 0
    for x in range(1, num+1):
        result += x
        print(result)
# 要注意缩进,以及分号的使用
# 函数调用
# 调用格式: 函数名(参数)这里参数是实参
def sum(num):
    result = 0
    for x in range(1, num+1):
        result += x
        print(result)
number = 1
sum(number)

案例

定义一个函数来实现用户的登录

def login():
    username = input('输入用户名')
    password = input('输入密码')
    if username == 'admin' and password == '123456':
        print('登录成功')
    else:
        print('登录失败')
login()

函数的参数

# 有参传参,无参空着,顺序一致
def milk_tea(n,kind='波霸奶茶'): # n表示奶茶数量,kind表示奶茶种类
    # 默认参数一定要在普通参数后,默认参数可以不传参使用默认值
    # 可以有很多默认参数但一定要在所有普通参数结束后再写默认参数
    for i in range(n):
        print('正在制作第{}杯奶茶'.format(i+1))
        print('放入{}的原材料'.format(kind))
        print('调制奶茶')
        print('倒入奶茶')
        print('封口')
milk_tea(5)
milk_tea(1, '珍珠奶茶')
milk_tea(4, '椰果奶茶')
milk_tea(5, '黑糖珍珠奶绿')

关键字参数

def milk_tea(n, kind='波霸奶茶',price=15): # n表示奶茶数量,kind表示奶茶种类
    print('顾客您需要的{},每杯{}元,应收{}元'.format(kind,price,n*price))
    for i in range(n):
        print('正在制作第{}杯奶茶'.format(i+1))
        print('放入{}的原材料'.format(kind))
        print('调制奶茶')
        print('倒入奶茶')
        print('封口')
milk_tea(1)
milk_tea(2, '原味奶茶')
milk_tea(n=4, kind='原味奶茶',price=18) # 关键字参数可以自定义传输

返回值

# 计算从1到num的和
def ger_sum(num):
    sum = 0
    for i in range(num):
        sum += i+1
    return sum
num1 = input('请输入要计算到的数字')
num1 = int(num1)
result = ger_sum(num1)
print('result = {}'.format(result))

第八讲

面向对象基础

一类人或一类车等的定义方法用列表太过复杂,所以抽象出类这一概念

面向过程编程(把大象放进冰箱需要几步)

  • 把冰箱门打开
  • 把大象装进去
  • 把冰箱门关上

面向对象编程(大象,冰箱的种类,具象化目标具象化实现)

类的定义

# class 类名:
#     属性
#     方法

要求

  1. 类的首字母必须大写

  2. 类名后面必须有冒号

  3. 类体有缩进

class Phone:
    pass
# 在python中 pass是空语句,是为了保持程序结构的完整性。pass不做任何事情,一般用于占位有语句,支撑结构
class Phone:
    brand = '华为'
    color = '黑色'
    type = 'Mate30 pro'
    price = 9999
# 定义行为和函数相似,只是必须带上一个参数self
    def call(self):
        print('打电话')
    def send_message(self):
        print('可以发信息')
class Saiya:
    name = '悟空'
    hair = '固定'
    has_tail = True
    appetite = '大'
    def fight(self):
        print('我们赛亚人就是喜欢战争')

类的使用

类的定义主要用途是把一个类的所有特征抽象出来,而用到具体对象时则需要讲抽象的特征一一赋值一一对应

# 对象名 = 类名(参数),其中参数是可选参数,可有可无
phone1 = Phone()
phone2 = Phone()
phone3 = Phone()
print(phone1)
print(phone2)
print(phone3)
# 访问方式  对象名.属性名  or   对象名.方法名
print(phone1.price)

属性添加的方式

  1. 通过外层的对象动态添加
  2. 使用构造函数添加
# 通过外层的对象动态添加
phone1.price = 10000
print(phone1.price)
# __init__魔术构造方法也就是构造函数,会在开始时自动调用
class Person:
    country = '中国'
    def __init__(self,name):
# self表示对象本身,self.name = name表示在当前对象中增加一个属性并且赋值(在这里也就是Person)
        print('我是一个__init__方法')
        self.name =name
    def eat(self):
        print('我是一个吃货')
p1 = Person(name = '龟龟')
p2 = Person(name = '兔兔')
print(p1)
print(p2)

类的方法的定义与调用

class Person:
    name = '悟空'
    def __init__(self,name):
        self.name =name
    def eat(self):
        print('我是一个吃货')
    def sprot(self, time):
        if time < 6:
            print(self.name + '你怎么这么勤快,这么早就起床了')
        else:
            print(self.name + '怎么这么爱睡懒觉!')
        self.eat()
p1 = Person(name = '龟龟')
p2 = Person(name = '兔兔')
p1.sprot(time=3)
p2.sprot(time=7)

类的继承

class Saiya:
    def __init__(self,name):
        self.name = name
    def eat(self):
        print(self.name + '我是一个吃货')

    def sprot(self, time):
        if time < 6:
            print(self.name + '你怎么这么勤快,这么早就起床了')
        else:
            print(self.name + '怎么这么爱睡懒觉!')
        self.eat()
# 假设有另外一类人的定义,和上面Person几乎一样,为了减少代码重复,引入继承
class Saiya(Person):
    #这样就可以表示Saiya类继承了所有Person属性和行为(可以任意调用Python),这样我们就有更多的代码空间进行Saiya不同于Person的特性,大大简化了代码

第九讲

模块(python的魔法棒)

  1. 模块简介
  2. 模块导入
  3. 包的导入
  4. 模块搜索路径
  5. __name__的使用
  6. 常见系统模块介绍
# 创建模块的本质就是创建一个.py文件,它可以被其他模块导入并使用
# 调用模块的方法
# import 
# from ... import
# 模块命名要用小写字母,且不要和内置模块重名
创建一个.py文件(harry.py)
# harry.py
name = 'Harry Potter'
age = 10
def Fight(tool=None):
    if tool:
        print('在魔法学校驾驶' + tool + '练习飞行')
    else:
        print('走到魔法学校就会练习飞行了!')
class Course:
    def __init__(self,name,c_list=[]):
        self.name = name
        self.c_list = []
    def add_course(self,c_name):
        if c_name:
            self.c_list.append(c_name)
        else:
            print('选修课不能为空')
    def remove_course(self,c_name):
        if c_name:
            self.c_list.remove(c_name)
        else:
            print('选修课不能为空')
再创建一个magic.py文件
# magic.py
def use_magic():
    print('我会施展厉害的魔法')

此时两个模块已经封装完毕,我们只需要import 模块名即可调用模块里面的函数变量以及类,我们的使用方式主要是通过点运算符来完成的

# 在包文件中进行调用(一般导入语句都在开头)
import harry
import magic
print(harry.name)
harry.Fight()
c = harry.Course('哈利')
c.add_course('黑魔法防御术')
magic.use_magic()
# 模块重命名
import harry as hy # 这样防止模块名字太长起到重命名的作用
# 导入方法2
from harry import name
from harry import Fight
from harry import Course
print(name)
Fight()
c = Course('哈利')
c.add_course('黑魔法防御术')
# 这种方法就不用使用harry.的方法,相当于提前声明来源,简化逻辑,也可以起到引入特定变量特定函数特点类的作用
# from harry import name
# from harry import Fight
# from harry import Course
也可以用以下表达代替用来简化代码
from harry import name, fight, Course
或者
from harry import *
# 这个表示把所有的都导入

导入模块从本质上来说就是去执行一个.py文件,开辟一个新内存,把导入的东西放进内存中,这样我们调用就可以直接从内存中获取,当模块数量越来越多时,我们就需要通过包的形式对模块进行管理

包就是一个包含__init__.py的文件夹

# 创建一个包(包的命名规则与模块相同)
# 右键点击new,然后创建python package

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2wsqM5f0-1630476391786)(C:\Users\dell\Desktop\QQ截图20210813172613.png)]

# 创建好以后将之前封装好的harry.py和magic.py拖到包中文件夹

包的导入

# 拖入后我们可以看到原来的导入格式被修改了
from package.harry import *
# 编译器自动维护了package.的格式表明路径
import sys
print(sys.path)
# 利用sys包我们可以查找我们当前脚本文件的位置
# 在新创建的包文件中创建magic1,magic2,text的.py文件
magic1.py
def use_magic():
    print('我会施展最厉害的魔法')
print('我是一个新的magic模块' + __name__)
text.py
from package.harry import *
from package.magic1 import use_magic
# __name__的用途在于,如果在它原本的模块运行,输出为__main__在别的模块运行则输出为路径。可以利用这一性质,来实现一些语句只模块内输出而不模块外输出
magic.py
def use_magic():
    print('我会施展最厉害的魔法')
if __name__ == '__main__':
    print('我是一个新的magic模块' + __name__)
这样'我是一个新的magic模块'这个语句就不会被误输出了!妙啊

系统内置模块

  • # time模块 
    # 可以获取当前的时间戳
    import time
    t1 = time.time()
    print(time.ctime(t1))
    # 利用sleep函数进行每隔一秒循环进行一次
    import time
    for i in range(5):
        print(i)
        time.sleep(1)
    # datetime
    # datetime中封装了date,time,datetime,timedelta其中timedelta是值时间差
    from datetime import *
    print(datetime.now())
    dt = datetime.now()
    dt1 = dt + timedelta(days=-1) # 表示日期-1
    print(dt, dt1, sep='\n')
    
  • # random模块
    import random
    print(random.random()) # 表示从0到1的随机小书
    print(random.randint(1, 10))
    # 表示从1到10的随机整数(包括1和10)
    print(random.randrange(1, 10))
    # 表示从1到10的随机整数(不包括10)
    print(random.choice(range(10)))
    # random.choice(列表或数据集),表示从列表或数据集中随机获取一个元素,起到定范围而又随机的作用
    
  • # os模块
    import os
    # 查看当前工作目录
    result1 = os.getcwd()
    print(result1)
    # 在当前文件夹中创建一个文件夹
    # os.mkdir()只能创建一级目录。而os.makedirs()可以创建多级目录。
    os.mkdir('images')
    # 获取当前环境变量
    print(os.environ)
    # 获取绝对路径
    result = os.path.abspath('harry.py')
    print(result)
    # os.listdir('package')查看文件列表
    # os.remove('package/text.py')删除某个模块
    注意以下操作只能针对同级或下级文件,如harry.py中使用下面代码则会报错,一定要在与package同级的.py文件中操作才有用
    result = os.listdir('package')
    print(result)
    os.remove('package/text.py')
    # 查看文件大小
    path = './package/harry.py' # .表示当前目录下
    result = os.path.getsize(path)
    print(result)
    # 查看是否为文件
    result1 = os.path.isfile('path')
    print(result1)
    # 查看是否为文件夹
    result1 = os.path.isdir('path')
    print(result1)
    

第十讲

python的文件操作(自动化记录)

  1. 文件写入
  2. 文件读取
  3. csv文件的写入
  4. csv文件的读取
# open()函数的使用,open函数的作用是打开一个文件并且有返回值(布尔类型)
# 文件要素:存放位置,文件名字
# 相对位置 ./main.py同一目录下的文件表示
# 绝对路径 D://user/hello/main.py
stream = open(file='./666') # 变量stream起到了传输管道的作用
print(stream)

输出结果为<_io.TextIOWrapper name=’./666’ mode=‘r’ encoding=‘cp936’>

mode = 'r’读操作,'w’写操作,'a’追加,'t’文本格式,'b’字节方式读取且这些字母可以组合使用

encoding表示编码集即翻译方式

# mode,encoding可以修改
stream = open(file='./666', mode='w')
print(stream)
stream = open(file='./666', mode='w', encoding='utf-8')
print(stream)

文件写入以及关闭

stream = open(file='./666', mode='w', encoding='utf-8')
print(stream)
record = '4月18日 17:00 FPX PK RNG'
stream.write(record) # 文件写入
stream.close() # 文件关闭 一定要关闭涉及数据安全
# 如果打开的文件不存在,则会新建一个文件
stream = open(file='./text1.txt', mode='w', encoding='utf-8')
print(stream)
# 将mode改成a即可实现不断追加,但追加并不会帮我们换行,所以当我们需要换行的时候需要在加入的文本前用换行符号
stream = open(file='./text1.txt', mode='a', encoding='utf-8')
print(stream)
record = '\n4月18日 17:00 FPX PK RNG'
stream.write(record) # 文件写入
stream.close()

那如果数据量很大怎么办呢

record = ['4月1日 17:00 IG PK RA',
          '4月2日 17:00 LGD PK SN',
          '4月3日 17:00 FPX PK RA',
          '4月4日 17:00 SN PK WE',
          '4月5日 17:00 JDG PK FPX',
          '4月6日 17:00 SN PK TEX'
          ]
stream = open('records.txt',mode='w',encoding='utf-8')
for record1 in record: # 通过循环来进行写入并在后面添加换行符号
    stream.write(record1 + '\n')
stream.close()
stream = open('records.txt',mode='a',encoding='utf-8')
# 再次写入的时候格式要变成a,并且重新打开
stream.write('123456')
stream.close()
# 写入后一定要关闭文件

那文件的读取改如何操作

stream = open('records.txt', mode='r', encoding='utf-8')
# 读取中格式为r
content = stream.read()
# 用一个变量保存我们阅读的值
print(content)
stream.close()
# 读格式和写格式有所不同,当写格式文件不存在的时候会创建一个文件,而读取一个不存在的文件则会报错

文件的异常处理(处理报错情况)

  • # 格式
    try:
        可能会有异常的代码
    except:
        发生异常的时候要执行的代码
    finally:
        无论是否有异常都要执行的代码
    
  • # 方法1
    content = None
    try:
        stream = open('records.txt', mode='r', encoding='utf-8')
        content = stream.read()
    except:
        print('文件找不到')
    finally:
        print(content)
     # 这段代码逻辑就是,设置变量为空,如果文件可以找到并打开,将改空代码重新赋值并且输出,如果文件无法找到并打开,则会输出except的提示语句,并且输出空。这样就可以避免了报错导致程序异常终止
    
  • # with关键字的使用
    with 表达式 as 变量:
        语句
    
  • with open('records.txt',mode='r',encoding='utf-8') as  stream:    content = stream.read()    print(content)
    

csv文件的操作

csv文件是以逗号隔开的

import csvrecord = [['4月1日 17:00 IG PK RA'],          ['4月2日 17:00 LGD PK SN'],          ['4月3日 17:00 FPX PK RA'],          ['4月4日 17:00 SN PK WE'],          ['4月5日 17:00 JDG PK FPX'],          ['4月6日 17:00 SN PK TEX']]with open('electronic_sport.csv', 'w', encoding='utf_8') as stream:    writer = csv.writer(stream)    writer.writerow(['date', 'time','adversary'])    for recod in record:    writer.writerow(recod)    # 也可以直接用writer.writerows来实现多行同时写入

文件写入不同操作系统的展示结果不同,windows常会附加空行

如有需要改变可以open(‘electronic_sport.csv’, ‘w’, encoding=‘utf_8’,newline = ‘’ )

csv文件的读取

with open('electronic_sport.csv', mode='r', encoding='utf-8') as stream:    reader = csv.reader(stream)    for row in reader:        print(row)

第十一讲

Pillow图片处理

PIL是python中一个强大而方便的图像处理库,Pillow是PIL的一个分支,我们在安装的时候尽量安装pillow,PIL和pillow不能共存,记得先卸载PIL哦!

如果遇到问题解决网址

Pycharm无法用pip安装PIL以及安装Pillow之后依然报错“No module named ‘Pillow’”的诡异问题_清水河C罗——Leonardo-Liu-CSDN博客

  1. Image模块的使用
  2. 其他模块的使用
    • ImageDraw
    • ImageFont
    • ImageFilter
# open()
# new()
# convert()
# 调用与展示
import PIL
from PIL import Image
image = Image.open(fp='证件照.jpg')
image.show()
# 注意图片要手动关闭,不然会占用程序进程

图片属性

print(image.size) # 大小返回一个二维坐标
print(image.mode) # 返回图像渲染模式RGB等
print(image.format) # 返回格式
# 如果不是本地文件则无法读取格式

convert函数

# convert函数可以改变图像渲染格式,1是一种渲染方式
image1 = image.convert('1')
image1.show()
mode描述
11位像素,黑白,每字节存储一个像素
L8位像素,黑白
P8位像素,使用调色板映射到任何其他模式
RBG3×8位像素,真彩
RBGA4×8位像素,带透明蒙版真彩
CMYK4×8位像素,分色
YCbCr3×8位像素,彩色视频格式
LAB3×8位像素,Lab颜色空间
HSV3×8位像素,色相,饱和度,值颜色空间
I32位有符号整数像素
F32位浮点像素

RGB是指色彩颜色的组合,R代表红,G代表绿,B代表蓝,就是红绿蓝的组合每个颜色值都可以在0到255取值,即用0到255量化各颜色的比例

构造新图像

image = Image.new('RGB', (220, 150), (150, 150, 255))
# new函数可以生成一个新图像,第一个是图像渲染方式,第二个是图像大小,第三个是你选中的图像渲染方式的参数,我们这里是RGB,所以填的数字即为红绿蓝的参数
image.show()

ImageFilter的方法

filter描述
BLUR模糊
CONTOUR轮廓
DETAIL详情
EDGE_ENHANCE边缘增强
EDGE_ENHANCE_MORE边缘增强更多
EMBOSS电磁波
FIND_ENGES寻找边缘
SHARPEN夏普
SMOOTH光滑
SMOOTH_MORE更光滑

本节案例为案例2

第十二讲

python之邮件操作

  1. 邮件相关协议介绍

    1. SMTP协议,即简单邮件传输协议,它是一组由源地址到目的地址传送邮件的规则,由它控制信件的中转方式(中转协议)
    2. POP3协议,即邮局协议第三版本,POP3允许用户从服务器上把邮件存储到本地主机上,同时删除保存在邮件服务器上的邮件(读取协议)
    3. IMAP协议,因特网报文存取协议(读取协议)
    4. 多途径Internet邮件扩展协议,它解决了SMTP协议只能传输ASCII文本的限制,把声音图像表格二进制数据这些作为邮件中[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lm7dARYe-1630476391787)(C:\Users\dell\Desktop\QQ截图20210815142825.png)]附件进行处理
  2. python中的邮件模块

    1. yagmail模块 发邮件模块
    2. keyring模块 访问系统密钥环服务
    3. schedule模块 定时任务执行器
    4. inbox模块 IMAP包进行IMAP操作
  3. 使用python发送邮件

  4. 使用python发送带附件的邮件

  5. 使用python接受邮件

import yagmail
yagmail.register('zhai18172675553@163.com', 'EHIQNPTYCGJMAKQD')

发邮件

yag = yagmail.SMTP(user='zhai18172675553@163.com', host='smtp.163.com')
contents = ['Hello world', '这是一封邮件,通过python发送,哈哈哈哈']
# 第一个参数是发送对象,第二个是主题,第三个是内容
yag.send('zhai18172675553@163.com', '欢迎python', contents)

那怎么处理文件呢,如字号字体格式等

发送富文本(HTML)邮件

yag = yagmail.SMTP(user='zhai18172675553@163.com', host='smtp.163.com')
contents = ['Hello world', '这是一封邮件,通过python发送,哈哈哈哈']
contents1 = ['<h3>Hello python</h3>', '<b>这是一封邮件,通过python发送</b>', 'hhhhhhhh']
yag.send('zhai18172675553@163.com', '欢迎python', contents1)

那怎么携带附件呢

yag = yagmail.SMTP(user='zhai18172675553@163.com', host='smtp.163.com')
contents = ['Hello world', '这是一封邮件,通过python发送,哈哈哈哈']
# 定义一个变量携带附件,然后再用正文列表携带就行
obj = yagmail.inline('text.txt')
contents1 = ['<h3>Hello python</h3>', '<b>这是一封邮件,通过python发送</b>', 'hhhhhhhh',obj]
yag.send('zhai18172675553@163.com', '欢迎python', contents1)

第十三讲

爬虫介绍

  1. 爬虫简介

    模拟浏览器,发送请求,获取响应

    原则上只要是客户端浏览器能做的事情,爬虫都能做

    爬虫也只能获取客户端浏览器所展示的数据

  2. 爬虫分类

    通用爬虫

    聚焦爬虫

    ​ 聚焦爬虫是面向特定主题需求的一种网络爬虫程序,它和通用爬虫的区别在于只抓取特点我们需要的信息

    根据目的可以分为

    1. 功能性爬虫

    2. 数据增量爬虫

    根据url地址和对应的页面内容是否改变,数据增量爬虫可分为

    1. 地址变内容也变的爬虫

    2. 地址不变内容变的爬虫

    url就是网址等

  3. 爬虫作用

    数据采集

    软件测试

    网络安全

  4. 技术步骤

    1. 爬取数据,实际上就是根据一个网址向服务器发起网络请求,获取服务器返回的数据
    2. 解析数据,将服务器返回的数据转换为人容易理解的样式
    3. 筛选数据,从大量的数据中筛选出需要的数据
    4. 存储数据
from urllib.request import Request
from urllib.request import urlopen

# 爬取百度首页
url1 = 'http://www.baidu.com'
# 用一个变量保存
request = Request(url=url1)
response = urlopen(request)
# print(response.read().decode('utf-8'))
# 获取的数据是源代码要用decode进行解码操作
html_string = response.read().decode('utf-8')
with open('baidu.html', 'w', encoding='utf-8') as fp:
    fp.write(html_string)

第十四讲

HTML基础

HTTP协议

HTTP协议也就是超文本传输协议,它是基础TCP协议的应用层传输协议,简单来说就是客户端和服务端进行数据传输的一种规则

并且HTTP是一种无状态协议,HTTP协议本身不会对发送过的请求和相应的通信状态进行持久化处理,主要是为了保持协议的简单性,从而提高效率

HTTP默认端口号是80

HTTPS协议默认端口号是443区别在于进行了加密

请求

HTTP协议中每次请求都会携带下方的内容,比如有请求的方法,请求的路径,协议的版本等我们称作请求行

操作

进入百度首页

右键检查

选择NETWORK也就是网络

刷新页面

点击www.baidu.com查看浏览器的信息,我们爬虫就是模拟浏览器去访问

爬虫中特别关注的请求头

无论是浏览器还是爬虫,在发出请求的时候都要遵守HTTP协议,遵守HTTP协议就要携带请求头

我的百度首页请求头

Accept: 
支持的代码类型
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
支持的编码方式
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
支持的语言
Cache-Control: max-age=0
控制缓冲值
Connection: keep-alive
状态
Cookie: BAIDUID=74AB3553F3D1843AA6627537EF425F8D:FG=1; BIDUPSID=74AB3553F3D1843AAF17FE022AC44843; PSTM=1611195247; __yjs_duid=1_51068de6ff007d2b17777ead3436db931621065947976; BD_UPN=12314753; BDUSS=djeGhzTUxpUVB5UmEwaDdpSGUzSG43a3JUVjhhWVJZMzF1VVFVSGFRLTdWMEZoSVFBQUFBJCQAAAAAAAAAAAEAAAB-HcmFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALvKGWG7yhlhQ2; BDUSS_BFESS=djeGhzTUxpUVB5UmEwaDdpSGUzSG43a3JUVjhhWVJZMzF1VVFVSGFRLTdWMEZoSVFBQUFBJCQAAAAAAAAAAAEAAAB-HcmFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALvKGWG7yhlhQ2; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; H_PS_645EC=055bRlxSoHG2G295mw9NfthZiq%2FzdtjGSsR9%2F%2FYvHbTiuqO0bQbO%2BUU0APw73WKpdX0KXw; BD_HOME=1; H_PS_PSSID=34438_34370_31660_34376_34004_34072_34092_34094_26350_22158_34388_34360; BAIDUID_BFESS=74AB3553F3D1843AA6627537EF425F8D:FG=1; BA_HECTOR=848l200l0l05248krb1ghn6ia0q
Host: www.baidu.com
Referer: https://cn.bing.com/
跳转界面出处
sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Microsoft Edge";v="92"
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) 
浏览器名称
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.73

响应

响应是HTTP访问的一个回传数据的过程

HTML

html是一种解释性语言

标签写法

<!--单标签-->
	<标签名 属性1='属性值' 属性2="属性值" 属性3=属性值>
<!--对标签-->
     <标签名 属性1='属性值' 属性2="属性值" 属性3=属性值>内容</标签名> 
        标签不能创造!

HTML的全局架构标签

<!doctype html>
<html>根标签
    <head>头部
        <meta charset="utf-8">告诉浏览器用utf-8编码格式解释文档
        <title>Document</title>文档标题
    </head>
    <body>
        
    </body>
</html>

常用标签

  • h1——h6标题,一般一个页面只设置一个h1标题

  • hr(单标签)水平分割线

    • width可以使用绝对值,300,不带单位也可以使用百分比
    • align对齐方式:left center right
  • p段落标签,有段前间距和段后间距

  • br(单标签)换行

  • nobr(双标签)不换行,所修饰的内容无论多长,不会自动换行,显示不下会有滚动条

  • pre保持原来的样式,无论空格还是换行都会正常显示

  • b加粗

  • i斜体

  • u下划线

  • sub/sup下标/上标,看圈在哪边,在下就是下标

  • font字体

    • face字体颜色,到window目录下font子目录下查看
    • color字体颜色
    • size值取1-7,7最大
  • blockquote引用,会从正常的文本中分离,留有左右边距

  • 实体引用

    • 空格 &nbsp
    • < &lt 等等
  • 列表

    • 有序列表(ol/li)
      • type 数字
      • start 开始标号,默认从1开始
    • 无序列表(ul/li)
      • type项目符号
        • disc默认 实心圆圈
        • square 实心方块
        • ciecle 实心圆圈
  • 超链接

    超链接写法

    <a href="http://www.baidu.com/">百度</a>
    

    href所请求的url,注意url必须写协议

  • img标签(单标签)

    <img src='' title='' alt='' border='' width=''height=''>
    
  • 表格

    • table表
      • border表格线
      • cellspacing单元格的间距
      • cellpadding单元格到内容距离
      • align水平对齐left,center,right
      • height可以不用设置,自动撑开
    • tr行
      • align水平对齐left,center,right
      • valign垂直对齐top,middle,bottom
      • 注意:如果没有给该表格设置高度,那么设置valign无效,在以后布局页面的时候,一般不使用valign,只有一种情况使用到,就是图片和文字平排排放的时候,需要设置图片的valign为middle
    • td单元格
      • colspan跨列 向右合并
      • rowspan跨行 乡下合并
    • th
      • 就是表格的表头,内容会加粗,和td用法相同
    • caption表格标题,跟随表格移动
<table border=1 width=100>
    <tr align='left'>
    	<td>A</td>
    	<td>A</td>
        <td>A</td>
    </tr>
    <tr align='left'>
        <td>B</td>
    	<td>B</td>
    	<td>B</td>
    </tr>
</table>
  • 表单(重要)
    • 用途:收集用户信息,提交给服务器
    • 基本使用
      • 不是所有的标签都可以提交,能够向服务器提交信息的表单项,只有表单项才可以向服务器提交信息
      • 表单项必须放到form标签中才可以提交信息
      • action提交地址,一般是服务器的页面
      • methon提交方式
      • enctype用于文件上传
  • input框
    • 公有属性
    • 单行文本框
    • 提交按钮

在Python中只要看得懂标签是干啥就行了

第十五讲

BeautifulSoup解析HTML标签

爬虫实战项目(英雄联盟虎扑论坛)

import requests
url = 'https://bbs.hupu.com/lol'
headers = {
    'user-agant':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.73'
}
response = requests.get(url=url, headers=headers)
print(response)

这一步输出结构是一个状态码,如果和浏览器状态码相同,则访问正常

# pip install reqeusts, lxml
import requests
from lxml import etree
import csv

url = 'https://bbs.hupu.com/lol-1'

headers = {
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15',
    'Host': 'bbs.hupu.com'
}

response = requests.get(url=url, headers=headers)
# print(response.text)

# with open('hupu.html', 'w', encoding='utf-8') as fp:
#     fp.write(response.text)

# 解析数据
# 数据解析的准备工作
root = etree.HTML(response.text)

names = root.xpath('//div[@class="bbs-sl-web-post"]/ul/li/div[@class="post-title"]/a/text()')
href = root.xpath('//div[@class="bbs-sl-web-post"]/ul/li/div[@class="post-title"]/a/@href')
author = root.xpath('//div[@class="bbs-sl-web-post"]/ul/li/div[@class="post-auth"]/a/text()')
time = root.xpath('//div[@class="bbs-sl-web-post"]/ul/li/div[@class="post-time"]/text()')

info = []
for i in range(len(names)):
    info.append([names[i], author[i], time[i], href[i]])

fieldnames = ['name', 'author', 'time', 'href']
f = open('hupudata.csv', 'a+', encoding='utf-8')
f_csv = csv.writer(f)
f_csv.writerows(info)
f.close()

第十五讲

数据保存之csv和excel

import requests
from lxml import etree
import json


# 请求数据的过程
def request_data(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
    }

    response = requests.get(url=url, headers=headers)
    with open('music.html', 'w', encoding='utf-8') as fp:
        fp.write(response.text)

    # 请求到的html字符串返回
    return response.text


# 解析函数
def parse_data(html_string):
    root = etree.HTML(html_string)
    ul_list = root.xpath('//div[@class="songList"]/ul')

    song_list = []
    for ul_node in ul_list:
        li_list = ul_node.xpath('./li')
        for li_node in li_list:
            song_list.append({'name': li_node.xpath('./a/text()')[0],
                              'href': li_node.xpath('./a/@href')[0]})

    return song_list


def save_data(items):
    fp = open('music.csv', 'a', encoding='utf-8')

    for item in items:
        json_string = json.dumps(item, ensure_ascii=False)
        fp.write(json_string + '\n')

    fp.close()


if __name__ == '__main__':
    html_string = request_data(url='https://www.1ting.com/song_n.html')

    song_list = parse_data(html_string)

    save_data(song_list)

第十六讲

数据分析三剑客

在电脑左下角搜索输入cmd进行命令提示符

输入jupyter notebook进入网页

进入网页后点击右方new进入编译界面

单元格操作(都在选中状态操作)

esc快速进入选中状态

enter快速进入编辑状态

  1. 增加单元格
    • 按b,在下面新增一个单元格
    • 按a,在上面新增一个单元格
  2. 删除单元格
    • 双击d,删除当前选择的单元格
  3. 剪切单元格
    • 单击x,剪切当前选中的单元格到剪切板内
  4. 粘贴单元格
    • 单击v,粘贴内容
  5. 操作撤销
    • 单击z

单元格模式介绍

  1. code

    在选中状态下按y键将快速进入code模式

  2. markdown

    在选中状态下按m键将进入markdown模式

ctrl+enter 实现单元格运行 code模式下运行代码,markdown模式下文本进入阅览状态

点击jupyter旁边的实现重命名

数据分析大剑客

  1. numpy

    矩阵,构造,运算,访问,赋值

  2. pandas

    基与numpy,提供一维数据和二维表格数据的业务处理(去重等)

  3. matplotlib

    数据可视化包

数据挖掘

sklearn

第十七讲

请一定要事先安装好anaconda并且在控制中心输入jupyter notebook进入编译环境!

numpy的使用

主要用于数据处理的基础方法

数组和列表的区别

数组要求数据类型保持一直,列表没有强制要求

# 导入模块并且重命名  当然重命名为npy也可以
import numpy as np
# 查看版本
np.__version__
# 构造数组
np.array([1,2,3,4,5])
# 二维数组结构构造
np.array([[1,2,3],[3,4,5]])

其实我们还有更多便捷的方式去构造数组去实现我们的需求

shift+tab键可以将说明文档展开

# 可以用元组的方式来表达数组的行列个数
# ones表示用1填充,zeros表示用1填充
np.ones(shape=(3,2,3))

那如果我们用其他数字填充改怎么办呢

一直用英文开头显然不现实也不全面

# 指定数组样式并指定填充数字
np.full(shape=(2,4,3),fill_value=6)

但是我们的代码不可能每次都是知道填充啥,我们需要引入随机数的概念

# 下面代码表示生成从1到10的随机数填充进2行3列的二维数组中
np.random.randint(1,10,size=(2,3))
# 下面代码表示生从0-1的浮点数填充到5行5列的数组中
np.random.random(size=(5,5))
# 下面代码表示从0到10生成含有26个数的等差数列
np.linspace(0,10,26)
# 下面代码表示从0到10,步长为1的数组数据
np.arange(0,10,1)

Numpy数组的访问问题

# 访问格式 array[index]
array = np.arange(0,10,1)
array[0]
# 这里我们可以看出数组的访问形式和列表的访问形式是一样的

但是数组有着更加强大的功能和操作

# 列表数组共有操作 切片
array[1:4]
# 数组可以将列表作为索引也就是index
array[[0,1,2,3]]

这其中的妙用不仅仅是可以定向选择输出我们想要的数据,而且可以实现数组重排列

这样我们有一个基础的元数组我们就可以不断衍生出新的数组,减少重复代码重复思考

array1 = array[[0,1,0,1,0,1,0,1,0,1,0,1]]
print(array1)

高级索引技巧

用布尔列表定向获取数据

# 生成一个简单点的数组,我们想要的就在他对应的方位用true不想要的用false,同理我们也可以联想到这样的方法也可以构造新的数组
array1 = np.array([1,2,3,4,5])
array1[[True,False,True,True,False]]

广播运算

array1 = np.array([1,2,3,4,5])array1 > 3

输出结果为

array([False, False, False,  True,  True])

我们还可以实现更加高级的设想

如果我们将广播运算中的广播放入索引当中呢

array = np.array([1,2,3,4,5,6,7,8,9,10,105])array1 = array[array>8]print(array1)

输出结果为

[  9  10 105]

那么高维数组我们该如何实现呢

array2 = np.random.randint(1,10,size=(3,3))# 输出array2所有元素array2# 输出array2中的第一行第一列array2[0][0]array[0,0]

Numpy数组的运算

arr1 = np.array([1,2,3])arr2 = np.array([[1],[2],[3]])arr1+arr2

结果是

array([[2, 3, 4],       [3, 4, 5],       [4, 5, 6]])本质是1 2 3    1 1 11 2 3    2 2 21 2 3    3 3 3

两大运算潜规则

  1. 缺失维度自动补充
  2. 缺失数据用已有的值填充

但是存在特殊情况

arr1 = np.array([1,2,3])arr2 = np.array([[1,2],[2,2]])# display()用来快捷输出display(arr1,arr2)# 因为这时候arr2如果要扩展一列不知道如何扩展,我们如果再执行arr1+arr2就会报错

报错信息

ValueError                                Traceback (most recent call last)<ipython-input-79-e489ba1ad4d1> in <module>----> 1 arr1+arr2ValueError: operands could not be broadcast together with shapes (3,) (2,2)

Numpy排序方法

data = np.random.permutation(10)data# 生成10个索引data.sort()data# 实现重排 从小到大

但这种排序方法原有的data结构会被破坏,我们一般采取别的方法,即既保留data结构又可以实现重排

data = np.random.permutation(10)datanp.sort(data)data

Numpy的拷贝方法

我们除了使用上述方法排序外,我们也可以拷贝原数据然后再更改拷贝数据,也能实现一样的效果

data = np.random.permutation(10)datac_date = data.copy()c_datec_date.sort()c_datedata

Numpy的级联方法

# 创建俩个数组arr1 = np.random.randint(1,10,size=(3,2))arr2 = np.random.randint(11,20,size=(3,3))# 第一个括号是放入我们要进行操作的数组,axis=0表示纵向级联,axis=1表示横向级联,默认为0np.concatenate((arr1,arr2),axis=1)

级联方法在业务处理上有关键作用

第十八讲

pandas的使用

pandas本质上是在numpy基础下进行的二次封装

主要用来解决业务逻辑

pandas主要提供了俩种对象

  1. Series(一维列表)
  2. DataFrame(二维列表)
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
Series([1,2,3])

输出结果

0    1
1    2
2    3
dtype: int64

左边有索引,但是显示的是默认索引,这给我们提供一个思路,也就是我们可以对索引进行重命名,让索引方式符合我们的日常使用习惯

Series([1,2,3],index=['tom','jack','lucy'])

输出结果

tom     1
jack    2
lucy    3
dtype: int64

Series的索引机制非常符合我们用户的习惯,像定向搜索等,所以Series更加适合去处理业务,提升可读性

访问类型

  1. 显示访问
s = Series([1,2,3],index=['tom','jack','lucy'])
s['tom']
s.loc['tom'] # 二者在访问上没有区别但推荐使用loc方法
  1. 隐式访问
s = Series([1,2,3],index=['tom','jack','lucy'])
s[0]

由于pandas是基于numpy的

numpy的访问方式在pandas中同样适用,如列表和布尔列表

s.loc[['tom','lucy']]

输出结果

tom     1
lucy    3
dtype: int64
s.loc[[True,False,True]]

输出结果

tom     1lucy    3dtype: int64

广播运算依然很有意义

s > 5
tom     Falsejack    Falselucy    Falsedtype: bool

DataFrame

引入了行标签和列标签

具有更加强大的现实意义

DataFrame(data=np.random.randint(0,10,size=(3,5)))

输出结果

01234
020184
167753
225455

直接输出了表格

哇哦!

我们在索引的时候还可以定制我们的行索引和列索引

甚至可以直接输出我们的成绩为表格状态

注:index 行索引 columns 列索引

DataFrame(data=np.random.randint(60,100,size=(3,6)),index=['一模','二模','三模'],columns=['语文','数学','英语','物理','化学','生物'])

输出结果

语文数学英语物理化学生物
一模939277996092
二模799579777177
三模916761687668

要不你也试试?

那如何访问DataFrame中的对象呢

df = DataFrame(data=np.random.randint(60,100,size=(3,6)),index=['一模','二模','三模'],columns=['语文','数学','英语','物理','化学','生物'])df.loc['三模','生物']

我们的索引方法是先写行索引再写列索引

我们还可以通过一些简单的操作访问一个人一二三模的生物成绩,或者一模的所有成绩(列表形势)

例如

df.loc[['三模','二模','一模'],'生物']

运算

  1. 索引对齐
  2. 广播
# 广播运算df+5df+df

那么就有一个问题

Series和DataFrame能进行运算嘛

答案当然是可以的

score = df.loc['一模']scoredf+score

输出结果

语文数学英语物理化学生物
一模178180182196136144
二模149174177183131156
三模183184172175152143

可以观察到进行了索引对齐的相加,所有数加上了一模所有学科的成绩

但这种方法是竖着加的那我们想横着加可以嘛

当然可以!

只不过会不对齐就会变成空值(NAN)

注:

axis=0表示纵向级联,axis=1表示横向级联,默认为0

不清楚可以看numpy使用哦!

df.add(score,axis=1)
语文数学英语物理化学生物
一模178180182196136144
二模149174177183131156
三模183184172175152143
df.add(score,axis=0)
语文数学英语物理化学生物
一模NaNNaNNaNNaNNaNNaN
三模NaNNaNNaNNaNNaNNaN
二模NaNNaNNaNNaNNaNNaN
化学NaNNaNNaNNaNNaNNaN
数学NaNNaNNaNNaNNaNNaN
物理NaNNaNNaNNaNNaNNaN
生物NaNNaNNaNNaNNaNNaN
英语NaNNaNNaNNaNNaNNaN
语文NaNNaNNaNNaNNaNNaN

大家看行标签应该就知道发生了什么

所以我们当进行相加的时候要注意索引是否一致

聚合运算

  1. 求和
  2. 求平均值
  3. 求方差

等等…

# 求和score.sum()# 平均值score.mean()# 方差score.var()# 标准差score.std()# 最大值score.max()# 最小值score.min()

我们试试让我们的对象进行这些运算

df.sum()
语文    243数学    268英语    258物理    260化学    215生物    227dtype: int64

我们发现默认是列相加

如果我们要改成行方向,只要用老方法改axis=1就行了

df.sum(axis=1)
一模    508二模    462三模    501dtype: int64

这些就可以算出每次考试的总成绩,大大简化运算

还有俩种非常好用的聚合方式

  1. any
  2. all
df.isnull()
语文数学英语物理化学生物
一模FalseFalseFalseFalseFalseFalse
二模FalseFalseFalseFalseFalseFalse
三模FalseFalseFalseFalseFalseFalse

这个函数方法可以判断我们的列表里面有没有空值

但这样全部显示是否有点不太雅观

# 全部为真才是真(score>10000).all()# 若至少一个值为真则为真(score>10000).any()

我们用any,all俩种方法配合判断语句可以实现很多复杂功能

第十九讲

Matplotlib实战数据分析

一定要在jupyter notebook编译环境中进行操作

主要内容

  1. 模板导入
  2. 随机曲线的生成
  3. 图像的操作
模板导入

导入我们数据分析三剑客,并且指令我们的图在本页面显示

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline
随机曲线的生成(折线图)
# 生成随机数值
x = np.random.randint(3,9,size=10)
# 指定画布相当于进行两行俩列的分割
plt.subplot(221)
plt.plot(x)

此时我们可以看到生成了一个随机的折线图

我们同样可以画一个正弦函数曲线

x = np.linspace(0,2*np.pi,10)
y = np.sin(x)
plt.subplot(221)
plt.plot(x,y)

这时候一张sinx函数的图就画好了

图像的操作

我们数据分析的时候当然不止一个图

怎么实现呢

plt.subplot(221)
plt.plot(x,y)

plt.subplot(222)

plt.subplot(223)

plt.subplot(224)

输出这些代码我们便得到了四张图(画布)

我们还可以设定横轴标签和一个纵轴标签

有一个问题就是matplotlib无法显示中文我们需要对他进行设置

plt.rcParams['font.sans-serif'] = 'SimHei'

然后标签就可以设置成中文了

plt.subplot(111)
plt.xlabel('中国')
plt.ylabel('国民收入',fontsize=20)

fontsize可以修改我们的字体大小,默认字体大小是10

条形图的绘制
# 生成一个4个数据的一维数组
data = np.random.randint(5,10,size=4)
data
# 指定行索引列高,由.bar生成条形图
plt.bar(x=['A','B','C','D'],height=data)
饼状图的绘制
# 设置画布比例确保是一个正常的圆
plt.figure(figsize=(5,5))
# 传入数据
plt.pie(x=data)
# 如果直接展示会有一大堆返回值,我们用show函数就可以清晰简单的得到那个园
plt.show()

但是只有一个饼显然信息不便表达,我们需要给他添加一些信息

plt.figure(figsize=(5,5))# 我们设置他的各个区域标签,然后autopct显示比例plt.pie(x=data, labels=list('ABCD'),autopct='%.2f%%')plt.show()

画图方法还有很多,本文只是介绍一些基础知识!

案例

import ImageFilter
import PIL
from PIL import Image
from PIL import ImageDraw, ImageFont, ImageFont
import random


def get_color():
    # get_color方法是通过随机数产生红绿蓝三个颜色的值构成RGB的调和色
    red = random.randint(0, 255)
    green = random.randint(0, 255)
    blue = random.randint(0, 255)
    return (red, green, blue)


def get_code(lenght):
    # get_code方法是通过随机选择,获取传入数字那么多的随机数字字母构成验证发
    s = '1234567890qwertyuiopasdfghjklzxcvbnm'
    code = ''
    for i in range(lenght):
        code += random.choice(s)
    return code


def draw_code():
    # 此函数方法用来绘制验证码
    # 指定画布的长度和宽度
    width = 120
    height = 40
    image_size = (width, height)
    # 定义画布
    image = Image.new('RGB', image_size, get_color())
    # 定义画笔
    draw = ImageDraw.Draw(image)
    # 指定字体和字体大小   tahoma.ttf是内置的一种字体,定义大小也可以不定义因为有默认的初始值
    myfont = ImageFont.truetype(font='tahoma.ttf', size=30)
    # 逐个绘制验证码字符
    code = get_code(4) # 先调用获取字符的函数来获取字符方便绘制
    for i in range(4):
        # 每绘制一个字母,x坐标改变y坐标不变也可以变化
        distance_x = random.randint(30 * i, 30 * i + 5)  # [0,10]
        distance_y = random.randint(0, 5)
        # draw.text(位置,内容,字体,填充颜色)
        draw.text((distance_x, distance_y), code[i], font=myfont, fill=get_color())
    # 干扰线和干扰点的数量也就是range后面的数字看自己需求不一定是10或20
    # 绘制干扰线
    for i in range(10):
        # 指定起始位置和终止位置
        begin = (random.randint(0, width), random.randint(0, height))
        end = (random.randint(0, width), random.randint(0, height))
        # 使用画笔来绘制干扰线,并通过fill绘制颜色
        draw.line((begin, end), fill=get_color())
    # 绘制干扰点
    for i in range(20):
        draw.point((random.randint(0, width), random.randint(0, height)), fill=get_color())
    # 滤镜边界加强
    image = image.filter(ImageFilter.EDGE_ENHANCE_MORE)
    image.show()


draw_code()

i

mport yagmail
import schedule
import time

# 定义工作任务,可以在工作任务中发送邮件或者做其他的事情

def task1():
    print("I'm working...")

# 群发邮件

def task2():
    yag = yagmail.SMTP(user='zhai1172675553@163.com', host='smtp.163.com')
    obj = yagmail.inline('证件照.jpg')
    contents = ['<h3>Hello Python!</h3>', '<b>这是一封邮件,通过Python发送', obj]
    # 收件人,邮件主题,正文内容
    yag.send(['zhai18172675553@163.com','1376500051@qq.com'], 'LOVE', contents)

# 发送周报邮件

def task3():
    yag = yagmail.SMTP(user='zhai18172675553@163.com', host='smtp.163.com')
    contents = ['<h3>Hello 领导们!</h3>', '<b>这是我的会议记录,请查收!</b>']
    # 收件人,邮件主题,正文内容
    yag.send('1376500051@qq.com', 'xxx的周报', contents)

# 其他的任务



# schedule.every(10).minutes.do(task1)   #部署每10分钟执行一次task1函数的任务

# schedule.every(10).hours.do(task1)   #部署每10小时执行一次task1函数的任务

schedule.every().day.at("10:30").do(task2)   #部署每天的10点办执行一次task2函数的任务
schedule.every().sunday.do(task3)   #部署每个周日执行一次task3函数的任务

while True:
    # 遍历所有schedule的语句
    schedule.run_pending()
    # 每俩秒在循环一次,防止循环频率太高占用过大内存
    time.sleep(2)

= 40
image_size = (width, height)
# 定义画布
image = Image.new(‘RGB’, image_size, get_color())
# 定义画笔
draw = ImageDraw.Draw(image)
# 指定字体和字体大小 tahoma.ttf是内置的一种字体,定义大小也可以不定义因为有默认的初始值
myfont = ImageFont.truetype(font=‘tahoma.ttf’, size=30)
# 逐个绘制验证码字符
code = get_code(4) # 先调用获取字符的函数来获取字符方便绘制
for i in range(4):
# 每绘制一个字母,x坐标改变y坐标不变也可以变化
distance_x = random.randint(30 * i, 30 * i + 5) # [0,10]
distance_y = random.randint(0, 5)
# draw.text(位置,内容,字体,填充颜色)
draw.text((distance_x, distance_y), code[i], font=myfont, fill=get_color())
# 干扰线和干扰点的数量也就是range后面的数字看自己需求不一定是10或20
# 绘制干扰线
for i in range(10):
# 指定起始位置和终止位置
begin = (random.randint(0, width), random.randint(0, height))
end = (random.randint(0, width), random.randint(0, height))
# 使用画笔来绘制干扰线,并通过fill绘制颜色
draw.line((begin, end), fill=get_color())
# 绘制干扰点
for i in range(20):
draw.point((random.randint(0, width), random.randint(0, height)), fill=get_color())
# 滤镜边界加强
image = image.filter(ImageFilter.EDGE_ENHANCE_MORE)
image.show()

draw_code()


i

```python
mport yagmail
import schedule
import time

# 定义工作任务,可以在工作任务中发送邮件或者做其他的事情

def task1():
    print("I'm working...")

# 群发邮件

def task2():
    yag = yagmail.SMTP(user='zhai1172675553@163.com', host='smtp.163.com')
    obj = yagmail.inline('证件照.jpg')
    contents = ['<h3>Hello Python!</h3>', '<b>这是一封邮件,通过Python发送', obj]
    # 收件人,邮件主题,正文内容
    yag.send(['zhai18172675553@163.com','1376500051@qq.com'], 'LOVE', contents)

# 发送周报邮件

def task3():
    yag = yagmail.SMTP(user='zhai18172675553@163.com', host='smtp.163.com')
    contents = ['<h3>Hello 领导们!</h3>', '<b>这是我的会议记录,请查收!</b>']
    # 收件人,邮件主题,正文内容
    yag.send('1376500051@qq.com', 'xxx的周报', contents)

# 其他的任务



# schedule.every(10).minutes.do(task1)   #部署每10分钟执行一次task1函数的任务

# schedule.every(10).hours.do(task1)   #部署每10小时执行一次task1函数的任务

schedule.every().day.at("10:30").do(task2)   #部署每天的10点办执行一次task2函数的任务
schedule.every().sunday.do(task3)   #部署每个周日执行一次task3函数的任务

while True:
    # 遍历所有schedule的语句
    schedule.run_pending()
    # 每俩秒在循环一次,防止循环频率太高占用过大内存
    time.sleep(2)
 类似资料: