python学习
常用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 真就假假就真
第四讲
条件语句
# 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
第五讲
循环语句
循环的核心在于减少重复代码,条件要尽量通用化
# 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('结束')
第六讲
数据类型列表(列表类似数组,字典类似结构体)
# 以前介绍的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
第七讲
函数
# 函数格式(定义)
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 类名:
# 属性
# 方法
要求
类的首字母必须大写
类名后面必须有冒号
类体有缩进
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)
属性添加的方式
# 通过外层的对象动态添加
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的魔法棒)
# 创建模块的本质就是创建一个.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的文件操作(自动化记录)
# 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博客
# 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 | 描述 |
---|---|
1 | 1位像素,黑白,每字节存储一个像素 |
L | 8位像素,黑白 |
P | 8位像素,使用调色板映射到任何其他模式 |
RBG | 3×8位像素,真彩 |
RBGA | 4×8位像素,带透明蒙版真彩 |
CMYK | 4×8位像素,分色 |
YCbCr | 3×8位像素,彩色视频格式 |
LAB | 3×8位像素,Lab颜色空间 |
HSV | 3×8位像素,色相,饱和度,值颜色空间 |
I | 32位有符号整数像素 |
F | 32位浮点像素 |
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之邮件操作
邮件相关协议介绍
python中的邮件模块
使用python发送邮件
使用python发送带附件的邮件
使用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)
第十三讲
爬虫介绍
爬虫简介
模拟浏览器,发送请求,获取响应
原则上只要是客户端浏览器能做的事情,爬虫都能做
爬虫也只能获取客户端浏览器所展示的数据
爬虫分类
通用爬虫
聚焦爬虫
聚焦爬虫是面向特定主题需求的一种网络爬虫程序,它和通用爬虫的区别在于只抓取特点我们需要的信息
根据目的可以分为
功能性爬虫
数据增量爬虫
根据url地址和对应的页面内容是否改变,数据增量爬虫可分为
地址变内容也变的爬虫
地址不变内容变的爬虫
url就是网址等
爬虫作用
数据采集
软件测试
网络安全
技术步骤
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(单标签)水平分割线
p段落标签,有段前间距和段后间距
br(单标签)换行
nobr(双标签)不换行,所修饰的内容无论多长,不会自动换行,显示不下会有滚动条
pre保持原来的样式,无论空格还是换行都会正常显示
b加粗
i斜体
u下划线
sub/sup下标/上标,看圈在哪边,在下就是下标
font字体
blockquote引用,会从正常的文本中分离,留有左右边距
实体引用
列表
超链接
超链接写法
<a href="http://www.baidu.com/">百度</a>
href所请求的url,注意url必须写协议
img标签(单标签)
<img src='' title='' alt='' border='' width=''height=''>
表格
<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>
在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快速进入编辑状态
单元格模式介绍
code
在选中状态下按y键将快速进入code模式
markdown
在选中状态下按m键将进入markdown模式
ctrl+enter 实现单元格运行 code模式下运行代码,markdown模式下文本进入阅览状态
点击jupyter旁边的实现重命名
数据分析大剑客
numpy
矩阵,构造,运算,访问,赋值
pandas
基与numpy,提供一维数据和二维表格数据的业务处理(去重等)
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
两大运算潜规则
但是存在特殊情况
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主要提供了俩种对象
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更加适合去处理业务,提升可读性
访问类型
s = Series([1,2,3],index=['tom','jack','lucy'])
s['tom']
s.loc['tom'] # 二者在访问上没有区别但推荐使用loc方法
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)))
输出结果
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
0 | 2 | 0 | 1 | 8 | 4 |
1 | 6 | 7 | 7 | 5 | 3 |
2 | 2 | 5 | 4 | 5 | 5 |
直接输出了表格
哇哦!
我们在索引的时候还可以定制我们的行索引和列索引
甚至可以直接输出我们的成绩为表格状态
注:index 行索引 columns 列索引
DataFrame(data=np.random.randint(60,100,size=(3,6)),index=['一模','二模','三模'],columns=['语文','数学','英语','物理','化学','生物'])
输出结果
语文 | 数学 | 英语 | 物理 | 化学 | 生物 | |
---|---|---|---|---|---|---|
一模 | 93 | 92 | 77 | 99 | 60 | 92 |
二模 | 79 | 95 | 79 | 77 | 71 | 77 |
三模 | 91 | 67 | 61 | 68 | 76 | 68 |
要不你也试试?
那如何访问DataFrame中的对象呢
df = DataFrame(data=np.random.randint(60,100,size=(3,6)),index=['一模','二模','三模'],columns=['语文','数学','英语','物理','化学','生物'])df.loc['三模','生物']
我们的索引方法是先写行索引再写列索引
我们还可以通过一些简单的操作访问一个人一二三模的生物成绩,或者一模的所有成绩(列表形势)
例如
df.loc[['三模','二模','一模'],'生物']
运算
# 广播运算df+5df+df
那么就有一个问题
Series和DataFrame能进行运算嘛
答案当然是可以的
score = df.loc['一模']scoredf+score
输出结果
语文 | 数学 | 英语 | 物理 | 化学 | 生物 | |
---|---|---|---|---|---|---|
一模 | 178 | 180 | 182 | 196 | 136 | 144 |
二模 | 149 | 174 | 177 | 183 | 131 | 156 |
三模 | 183 | 184 | 172 | 175 | 152 | 143 |
可以观察到进行了索引对齐的相加,所有数加上了一模所有学科的成绩
但这种方法是竖着加的那我们想横着加可以嘛
当然可以!
只不过会不对齐就会变成空值(NAN)
注:
axis=0表示纵向级联,axis=1表示横向级联,默认为0
不清楚可以看numpy使用哦!
df.add(score,axis=1)
语文 | 数学 | 英语 | 物理 | 化学 | 生物 | |
---|---|---|---|---|---|---|
一模 | 178 | 180 | 182 | 196 | 136 | 144 |
二模 | 149 | 174 | 177 | 183 | 131 | 156 |
三模 | 183 | 184 | 172 | 175 | 152 | 143 |
df.add(score,axis=0)
语文 | 数学 | 英语 | 物理 | 化学 | 生物 | |
---|---|---|---|---|---|---|
一模 | NaN | NaN | NaN | NaN | NaN | NaN |
三模 | NaN | NaN | NaN | NaN | NaN | NaN |
二模 | NaN | NaN | NaN | NaN | NaN | NaN |
化学 | NaN | NaN | NaN | NaN | NaN | NaN |
数学 | NaN | NaN | NaN | NaN | NaN | NaN |
物理 | NaN | NaN | NaN | NaN | NaN | NaN |
生物 | NaN | NaN | NaN | NaN | NaN | NaN |
英语 | NaN | NaN | NaN | NaN | NaN | NaN |
语文 | NaN | NaN | NaN | NaN | NaN | NaN |
大家看行标签应该就知道发生了什么
所以我们当进行相加的时候要注意索引是否一致
聚合运算
等等…
# 求和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
这些就可以算出每次考试的总成绩,大大简化运算
还有俩种非常好用的聚合方式
df.isnull()
语文 | 数学 | 英语 | 物理 | 化学 | 生物 | |
---|---|---|---|---|---|---|
一模 | False | False | False | False | False | False |
二模 | False | False | False | False | False | False |
三模 | False | False | False | False | False | False |
这个函数方法可以判断我们的列表里面有没有空值
但这样全部显示是否有点不太雅观
# 全部为真才是真(score>10000).all()# 若至少一个值为真则为真(score>10000).any()
我们用any,all俩种方法配合判断语句可以实现很多复杂功能
一定要在jupyter notebook编译环境中进行操作
导入我们数据分析三剑客,并且指令我们的图在本页面显示
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)