python从入门到入土

一、基础语法

1.字变量

字变量:在代码中,被写下来的固定的值

字符串:python中用双引号包裹起来的都是字符串

"""
本代码演示了
-各类字变量的写法
-通过print语句输出各类字变量
"""

# 写一个整数字变量
666
# 写一个浮点数字变量
13.14
# 写一个字符串字变量
"你不困我困"

print(666)
print(13.14)
print("你不困我困")

2. 注释

#单行注释

“”“注释内容”“” 多行注释

3. 变量

在程序运行时,能存储计算结果或能表示值的抽象概念,用来积记录数据

4.数据类型

  • 在print语句中,直接输出类型信息

    print(type(666))
    
  • 用变量存储type()的结果

    string_type=type("你不困我困")
    
  • 可以查看字变量和变量的类型

  • 变量无类型,但是它存储的数据有

# 方式1:使用print语句直接输出类型信息
print(type(666))

# 方式2:使用变量存储type()语句的结果
string_type = "你不困我困"
print(type(string_type))

# 方式3:使用type()语句,查看变量中存储的数据类型信息
name = "你不困我困"
print(type(name))

5. 数据类型转换

  • 数据类型转化,是以后经常需要使用的功能
    • 从文件中读取的数字,默认是字符串,需要转换为数字类型
    • input()语句,默认结果是字符串,若需要数字也需要转换
    • 将数字转换为字符串用以写出到外部系统
语句(函数) 说明
int(x) 将x转化为一个整数
float(x) 将x转换为一个浮点数
str(x) 将x转换为字符串

5. 标识符

  • 在python中,可以给很多东西取标识符

    • 变量的名字
    • 方法的名字
    • 类的名字
  • 是用户在编程的时候所使用的一系列名字,用于给变量、类、方法等命名

  • Python中,标识符命名的规则

    • 内容限定
      • 标识符命名中只允许出现:英文、中文、数字、下划线_
      • 不推荐使用中文
      • 数字不可以作为开头
    • 大小写敏感
      • 大小写是能完全区分的
    • 不可使用关键字
  • 变量的命名

    • 明了
    • 下划线命名法
    • 全部小写
# 将数字类型转换为字符串
num_str = str(11)
print(type(num_str), num_str)

float_str = str(11.345)
print(type(float_str), float_str)

# 将字符串转换为数字
num = int("11")
print(type(num), num)

num2 = float("11.345")
print(type(num2), num2)

# 整数转浮点数
float_num = float(11)
print(type(float_num), float_num)

# 浮点数转整数 会丢失精度
int_num = int(11.34)
print(type(int_num), int_num)

6. 运算符

# 算术运算符
print("1+1= ", 1+1)
print("1-1= ", 1-1)
print("1*2= ", 1*1)
print("2/1= ", 2/1)
print("21//2= ", 21//2) # 整除
print("2**2 = ", 2**2)

# 赋值运算符
num = 1+2*3
print("num=", num)
# 复合赋值运算符
num2 = 1
print("num2 =", num2)
num2 += 1
print("num2+1 =", num2)

7. 字符串扩展

  • 字符串的三种定义方式

    1.单引号定义法:name='你不困我困'
    2.双引号定义法:name="你不困我困"
    3.三引号定义法:name="""你不困我困"""  # 不用变量接收就是注释
    
    • 字符串的引号嵌套:
      • 单引号定义法:可以内含双引号
      • 双引号定义法:可以内含单引号
      • 可以使用转义字符 \ 将引号接触效用,变成普通字符
  • 字符串拼接

    # 字符串字变量之间的拼接
    print("1.你不困" + "我困")
    
    # 字符串字变量和字符串变量的拼接,必须是两个字符串间拼接
    name = "我困"
    tel = "111111"
    print("2.你不困" + name + ",我的电话是:" + tel)
    
  • 字符串格式化

    # 通过占位的形式,完成拼接
    name = "翻斗花园"
    message = "3.胡图图住在:%s" % name
    print(message)
    
    # 通过占位的形式,完成数字和字符串的拼接
    class_num = 57
    avg_salary = 9989
    message = "4.胡英俊的工号是%d,工资是%d" % (class_num, avg_salary)
    print(message)
    
  • 字符串格式化的精度控制

    • 可以使用辅助符号m.n 来控制数据的宽度和精度

      m,控制宽度,要求数字(很少使用),设置的宽度小于数字自生,不生效

      .n,控制小数点精度,要求是数字,会进行小数的四舍五入

    num1 = 11
    num2 = 11.2345678
    print("数字11宽度限制5,结果是:%5d" % num1)
    print("数字11宽度限制1,结果是:%1d" % num1)
    print("数字11.2345678宽度限制7,小数精度2,结果是:%7.2f" % num2)
    print("数字11.2345678小数精度2,结果是:%.2f" % num2)
    
  • 字符串格式化2

    f"{变量}…"

    • 不在意类型
    • 不会做精度控制
    name = "翻斗花园"
    address = 112
    mam = "张小丽"
    print(f"胡图图住在{name}{address}室,妈妈是{mam}")
    
  • 对表达式进行格式化

8. 数据输入

  • input语句的功能是获取键盘输入的数据
  • 可以使用,input(提示信息),用以在使用者输入内容之前显示提示信息
  • 要注意,无论键盘输入什么类型的数据,获取的数据永远都是字符串类型

二、python判断语句

1. if语句的基本格式

if 要判断的条件:
	 条件成立时,要做的事

2. range()

  • range(num)

    获取一个从0开始,到num结束的数字序列(不含num本身)

  • range(num1,num2)

    获取一个从num1开始,到num2结束的数字序列(不包含num2本身)

  • range(num1,num2,step)

    获取一个从num1开始,到num2结束的数字序列(不包含num2本身)

    数字之间的步长,以step为准,默认是1

三、循环语句

1. while

# 无限次机会,每次猜不着会提示,猜中数字后会提示猜了几次
import random
num = random.randint(1, 100)

# 通过一个布尔类型的变量,做循环是否继续的标记
flag = True
# 定义一个变量,记录总共猜测了几次
count = 0
while flag:
    guess_num = int(input("请输入您猜测的数字:"))
    count += 1
    if guess_num == num:
        print("猜中了!")
        # 设置flag就是循环终止的条件
        flag = False
    else:
        if guess_num > num:
            print("您猜测的数据较大!")
        else:
            print("您猜测的数据较小!")
print(f"您总共猜测了{count}次")
# i = 0
# while i < 10:
#     print("你不困")
#     i += 1

# 通过while循环,计算1累加到100的和
i = 1
sum_i = 0
while i <= 100:
    sum_i += i
    i += 1
print(f"1到100的累加和为:{sum_i}")

i = 1
while i <= 10:
    print(f"今天是表白的第{i}天,")

    j = 1
    while j <= 3:
        print(f"送第{j}只玫瑰")
        j += 1

    print("tutu I love you")
    i += 1

i -= 1
print(f"坚持到第{i}天,表白成功")
i = 1
while i <= 9:
    j = 1
    while j <= i:

        # 内层循环的print语句,不要换行
        # 通过\t制表符来对齐
        print(f"{j}*{i}={j*i}\t", end='')
        j += 1

    i += 1
    # print()就是换行
    print()


2. for

name = "nibukunwokun"
# 将name中的内容,挨个输出赋予x变量
# 就可以在循环体中对x进行处理
for x in name:
    print(x, end='')

# for 变量 in 待处理数据集
# 同while循环不同,for循环无法定义循环条件

# 统计如下字符串有多少个u
name = "nibukunwokun"
count = 0
for x in name:
    if x == "u":
        count += 1
print(f"{name}中有{count}个u")

# 打印九九乘法表
# 通过外层循环控制行数
for i in range(1, 10):
    # 通过内存循环控制每一行的输出
    for j in range(1, i+1):
        print(f"{j}*{i}={j*i}\t", end='')
    # 外层循环可以通过print输出一个回车符
    print()

3. range()

# for x in range(10):
#     print(x, end='')
# print()
#
# for x in range(2, 5):
#     print(x, end='')
# print()
#
# for x in range(2, 10, 2):
#     print(x, end='')

for x in range(10):
    print("送玫瑰花")

4. 循环中断

# 演示循环中断语句continue
# for i in range(1, 6):
#     print("语句1")
#     continue          # 结束本次循环,开始下次循环
#     print("语句2")    # 不会执行

# 演示continue的嵌套应用
# for i in range(1,6):
#     print("语句1")
#     for j in range(1, 6):
#         print("语句2")
#         continue
#         print("语句3")
#     print("语句4")

# 演示循环中断语句 break
# for i in range(1, 100):
#     print("语句1")
#     break   # 循环直接终止
#     print("语句3")
# print("语句2")

# 演示break的嵌套应用
for i in range(1, 6):
    print("语句1")
    for j in range(1, 6):
        print("语句2")
        break
        print("语句3")
    print("语句4")


四、函数

函数:是组织好的,可重复使用的,用来实现特定功能的代码段

# 统计字符串的长度,不使用内置函数len()
str1 = "nibukun"
str2 = "wokun"
str3 = "hututu"


# count = 0
# for i in str1:
#     count += 1
# print(f"字符串 {str1} 的长度是: {count}")

# 可以使用函数来优化整个过程
def my_len(data):
    count = 0
    for i in data:
        count += 1
    print(f"字符串 {data} 的长度是{count}")


my_len(str1)
my_len(str2)
my_len(str3)

为了得到一个针对特定需求,可供重复利用的代码段,提高程序的复用性,减少重复性代码,提高开发效率

1. 函数的定义

def 函数名(传入参数):
	函数体
	return 返回值
  • 参数如不需要,可以省略
  • 返回值如不需要,可以省略
  • 函数必须先定义后使用

2. 函数的传入参数

传入参数的功能:在函数进行计算的时候,接受外部提供的数据

# 定义两数相加的函数,通过参数接收被计算的两个数字
def my_add(x, y):
    result = x + y
    print(f"{x}+{y}的计算结果是:{result}")


# 调用函数,传入被计算的两个数字
my_add(1, 2)
  • 传入参数的数量是不受限制的

3. 函数返回值

  • 掌握函数返回值的作用

  • 掌握函数返回值的定义语法

def 函数(参数...):
	函数体
	return 返回值

变量 = 函数(参数)
  • 函数返回字

    函数在执行完成后,返回给调用者的结果

  • 返回值的应用语法:

    使用关键字:return 来返回结果

  • 注意

    函数体在遇到return后就结束了,所以写在return后的代码不会执行

  • 无返回值的函数,实际上就是返回了:None这个字变量

    • 在if判断上
      • None等同于False
      • 一般用于函数中主动返回None,配合if判断做相关处理

4. 变量在函数中的作用域

变量作用域指的是变量的作用范围(变量在哪里可以使用,在哪里不可以使用)

主要可以分为两类:局部变量和全局变量

  • 局部变量:定义在函数体内部的变量,只在函数体内部生效

    作用:子啊函数体内部,临时保存数据,当函数调用完成后,立刻销毁局部变量

  • 全局变量:在函数体内,外都可以生效的变量

  • 使用global关键字,可以将函数内部变量声明为全局变量

五、Python数据容器

1. 数据容器入门

  • 什么是数据容器

    一个可以容纳多份数据的数据类型,容纳的每一份数据称之为一个元素,每一个元素可以是任意类型的数据

  • 数据容器根据其特点的不同,可以分为:

    • 是否支持重复元素
    • 是否可以修改
    • 是否有序

    分为5类:列表,元组,字符串,集合,字典

2. 列表(list)

# 字变量
[元素1,元素2,元素3,.....]

# 定义变量
变量名称 = [元素1,元素2,元素3,.....]

# 定义空列表
变量名称 = []
变量名称 = list
  • 以[]作为标识

  • 列表内每个元素用逗号隔开

  • 使用下标索引,取出特定位置的数据(下标从0开始,依次递增/或者逆序,从下标-1开始)

列表除了可以

  • 定义和使用下标索引获取值

还提供了一系列的功能(列表的方法)

  • 插入元素
  • 删除元素
  • 清空列表
  • 修改元素
  • 统计元素个数

函数是一个封装的代码单元,可以提供特定功能,在Python中,如果将函数定义为class(类)的成员,那么函数会称之为方法

class 方法名:
	函数
# Student方法
class Student:
    def add(self,x,y):
        return x+y
    
# 方法的使用
student = Student()
num = student.add(1,2)
  • 查询某元素的下标

    功能:查找指定元素在列表的下标,如果找不到,就会报错ValueError

    列表.index(元素)	# index就是列表对象(变量)内置的方法(函数)
    
  • 修改特定位置(索引)的元素值

    列表[下标] =# 直接对指定下标(正向、反向下标均可)的值进行重新赋值
    
  • 插入元素

    列表.insert(下标,元素) # 在指定的下标位置,插入指定的元素
    
  • 追加元素

    列表.append(元素),将指定元素,追加到列表的尾部	# 追加单个元素
    列表.extend(其他数据容器)	# 将其他数据容器的内容取出,依次追加到列表尾部
    
  • 删除元素

    del列表[下标]
    列表.pop(下标)		# 可将删除元素进行记录
    
  • 删除某元素在列表中的第一个匹配项

    列表.remove(元素)
    
  • 清空列表

    列表.clear()
    
  • 统计某元素在列表中的数量

    列表.count(元素)
    
  • 统计列表内,有多少元素

    len(列表)
    
  • 列表的特点

    • 可以容纳多个元素
    • 可以容纳不同类型的元素(混装)
    • 数据是有序存储的(有下标序号)
    • 允许重复数据存在
    • 可以修改(增加或者删除元素)

3. list的遍历

将容器内的元素依次取出进行处理的行为,称之为遍历或者迭代

  • while循环

    • 通过列标[下标]的方式取出
    def list_while_func():
        my_list = ["胡图图", "张小丽", "胡英俊"]
        """
        循环控制变量通过下标索引来控制,默认0
        每一次循环将下标索引+1
        循环条件:下标索引变量<列表的元素数量
        """
        # 定义一个变量用来标记列表的下标
        index = 0
        while index < len(my_list):
            element = my_list[index]
            print(f"列表的元素:{element}")
            index += 1
    
    
    list_while_func()
    
  • for循环

    for 临时变量 in 数据容器:
        对临时变量进行处理
    

    表示,从容器中,依次取出元素并赋值到临时变量上,在每一次的循环中,我们可以对临时变量进行处理

    def list_for_func():
        my_list = [1, 2, 3, 4, 5]
        for element in my_list:
            print(f"列表的元素:{element}")
    
    
    list_for_func()
    
  • while循环适用于任何想要循环的场景

  • for循环适用于,遍历数据容器的场景和简单的固定次数循环场景

4. 元组(tuple)

  • 元组和列表一样,都可以封装多个,不同类型的元素在内,但是最大的不同点在于:元组一旦定义完成,就不可再被修改

    # 定义元素字变量
    (元素,元素....元素)
    # 定义元组变量
    变量名称 = (元素,元素....元素)
    # 定义空元组
    变量名称 = ()
    变量名称 = tuple()
    
  • 注意:元组中只有一个数据,这个数据后面要添加括号

  • 元组的相关操作

    编号 方法 作用
    1 index() 查找某个数据,如果数据存在返回对应的下标,否则报错
    2 count() 统计某个数据在当前元组中出现的次数
    3 len(元组) 统计元组内的元素个数
  • 元组的元素不可以变,但是如果元组的元素包括list,可变list中的内容

5. 字符串

  • 同元组一样,不可修改

  • 字符串的相关操作

    方法 作用
    字符串.index(字符串) 查找特定字符串的下标索引值
    字符串.replace(字符串1,字符串2) 将字符串中全部字符串1替换为字符串2(不是修改字符串本身,而是得到一个新字符串)
    字符串.split(分隔符字符串) 按照指定的分隔符字符串,将字符串划分为多个字符串,并存入列表对象中(字符串本身不变,而是得到了一个列表对象)
    字符串.strip() 去除前后的空格
    字符串.strip(字符串) 去除前后指定字符串

6. 数据容器的切点

  • 序列:内容连续,有序,可使用下标索引的一类数据容器

    列表,元组,字符串均可视为序列

  • 切片:从一个序列中,取出一个子序列

    # 从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列
    # 步长为负数表示反向标记
    # 对序列进行切片操作不会影响序列本身,而是得到一个新的序列
    序列[起始下标:结束下标:步长]
    
    # 对list进行切片,从1开始,4结束,步长1
    my_list = [0, 1, 2, 3, 4, 5, 6]
    result1 = my_list[1:4:1]
    print(f"结果1:{result1}")
    
    # 对tuple切片,从头开始,到最后结束,步长1
    my_tuple = (0, 1, 2, 3, 4, 5, 6)
    result2 = my_tuple[:]   # 起始和结束可以默认不写表示从头到尾,步长1可以省略
    print(f"结果2:{result2}")
    
    # 对str进行切片,从头开始,到最后结束,步长2
    my_str = "01234567"
    result3 = my_str[::2]
    print(f"结果3:{result3}")
    
    # 对str进行切片,从头开始,到最后结束,步长-1
    result4 = my_str[::-1]  # 等同于将序列反转
    print(f"结果4:{result4}")
    
    # 对列表进行切片,从3开始到1结束,步长-1
    my_list = [0, 1, 2, 3, 4, 5, 6]
    result5 = my_list[3:1:-1]
    print(f"结果5:{result5}")
    
    # 对元组进行切片,从头开始,到最后结束,步长-2
    result6 = my_tuple[::-2]
    print(f"结果6:{result6}")
    

7. 集合(set)

  • 基本定义语法

    # 定义集合字变量
    {元素,元素......元素}
    # 定义集合变量
    变量名称 = {元素,元素......元素}
    # 定义空集合
    变量名称 = set()
    
  • 集合是无序的,所以集合不支持下标索引访问,但是集合和列表一样,允许修改

  • 集合的相关操作

    方法 作用
    集合.add(元素) 将指定元素,添加到集合内
    集合.remove(元素) 将指定元素,从集合内移除
    集合.pop() 从集合中随机取出一个元素
    集合1.difference(集合2) 取出集合1和集合2的差集(集合1但是集合2没有的),得到一个新集合,集合1,2 不变
    集合1.difference_update(集合2) 对比集合1和集合2,在集合1内,删除和集合2相同的元素,集合1被修改,集合2不变
    集合1.union(集合2) 将集合1和集合2组成新集合,得到新集合,集合1,2 保持不变
    len(集合) 得到一个整数,记录了集合的元素数量

8. 字典/映射(dict)

  • 字典的定义

    存储的是键值对

    # 定义字典字变量
    {key:value,key:value......key:value}
    # 定义字典变量
    my_dict = {key:value,key:value......key:value}
    # 定义空字典
    my_dict = {}
    my_dict = dict()
    
  • key和value可以是任意数据类型,但是key不能为字典

  • 字典是可以嵌套的

  • 字典的相关操作

    方法 作用
    dict[key] = value 字典被修改,新增了元素
    dict[key] = value 字典key不可以重复,若对已经存在的key执行,相当于更新value值
    dict.pop(key) 获取指定key的value,同时字典被修改,指定key的数据被删除
    dict.keys() 得到字典的全部key

    六. Python函数进阶

1. 函数的多返回值

# 演示使用多个变量,接收多个返回值
def test_return():
    return 1, "hello", True


x, y, z = test_return()
print(x)
print(y)
print(z)

2. 函数的多种参数使用形式

  • 函数参数种类

    使用方式的不同,常见4中参数的使用方式:

    位置参数、关键字参数、缺省参数、不定长参数

  • 位置参数:调用函数时,根据函数定义的参数位置来传递函数【注意:传递的参数和定义的参数的顺序及个数必须一致】

  • 关键字参数:函数调用时通过”键 = 值“形式传递参数

    作用:可以让函数更加清晰,容易使用,同时也消除了参数的顺序要求【注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序】

  • 缺省参数:也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值【注意:所有位置参数必须出现在默认参数前,包括函数定义和调用】

    作用:当调用函数时没有传递参数,就会使用默认缺省参数对应的值

  • 不定长参数:也叫可变参数,用于不确定调用时会传递多少个参数的场景

    作用:当调用函数时不确定参数个数时,可以使用不定长参数

    • 位置传递的不定长【注意:传进的所有参数都会被不定长参数收集,它会根据传进参数的位置合并为一个元组】
    • 关键字传递的不定长【注意:参数是键 - 值形式下,所有的键值对会被接收,然后组成dict】
def user_info(name, age, gender):
    print(f"姓名是:{name},年龄是:{age},性别是:{gender}")


# 位置参数(默认使用形式)
user_info("胡图图", 20, "男")
# 关键字参数
user_info(name="胡英俊", gender='男', age=40)


# 缺省参数
def user_info2(name, age, gender='男'):
    print(f"姓名是:{name},年龄是:{age},性别是:{gender}")


user_info2('牛爷爷', 70)


# 不定长 - 位置不定长,*号
# 不定长定义的形参会作为元组存在,接收不定长数量的参数传入
def user_info3(*args):
    print(f"args参数的类型是:{type(args)},内容是:{args}")


user_info3(1, 2, 3, 4, '小美')


# 不定长 - 关键字不定长,**号
def user_info4(**kwargs):
    print(f"kwargs参数的类型是:{type(kwargs)},内容是:{kwargs}")


user_info4(name="胡图图", age=10)

3. 函数作为参数传递

  • 是计算逻辑的传递,不是数据的传递
  • 函数本身可以作为参数,传入另一个函数中进行使用
  • 将函数传入的作用在于:传入计算逻辑而非传入数据

七. Python文件操作

1. 文件的编码

  • 编码技术:即翻译的规则,记录了如何将内容翻译成二进制,以及如何将二进制翻译回可识别内容

  • 常用编码:UTF-8, GBK,Big5

    不同编码翻译内容不一样

2. 文件的读取

  • OS以文件为单位管理磁盘中的数据,一般来说,文件可以分为文本文件、视频文件、音频文件、图像文件、可执行文件等
  • 主要操作:打开、关闭、读、写
  • 通常可分为三步:打开文件、读写文件、关闭文件
  • 常用方法:
方法 解释
open() 可以打开或者创建一个新文件
文件对象.read(num) 表示从文件中读取的数据的长度(单位是字节),如果没有传入num,则读全部
文件对象.readlines() 按照行的形式八整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
文件对象.readline() 一次读取一行内容
文件对象.close() 关闭文件对象,也就是关闭对文件的使用
with open 语法 可以在操作完成后自动关闭文件,避免遗忘close方法
"""
name:要打开的目标文件名的字符串(可以包含文件所在的具体路径)
mode:设置打开文件的模式(访问模式):只读、写入、追加等
encoding:编码格式(一般使用UTF-8)
"""
open(name,mode,encoding)
"""
mode = 
r:以只读方式打开文件,文件的指针将会放在文件的开头,这是默认方式
w:打开一个文件只用于写入,如果该文件已存在则打开文件,并从开头开始编辑,原有内容会被删除,如果文件不存在,则创建新文件
a:打开一个文件用于追加,如果该文件已经存在,新内容会被写入已有内容之后,如果文件不存在,创建新文件并写入
"""
# 打开文件
f = open("D:/桌面/python/test.txt", "r", encoding="UTF-8")
print(type(f))

# 读取文件 read()
print(f"读取10个字节的结果:{f.read(10)}")
print(f"读取全部内容的结果:{f.read()}")  # 多次调用read会在上一次调用基础上调用

# 读取文件 readLines()  读取文件的全部行,封装到列表中
lines = f.readlines()
print(f"lines对象的类型:{type(lines)}")
print(f"lines对象的内容是:{lines}")

# 读取文件 readLine()
line1 = f.readline()
line2 = f.readline()
line3 = f.readline()
print(f"第一行数据是{line1}")
print(f"第二行数据是{line2}")
print(f"第三行数据是{line3}")

# for循环读取文件行
for line in f:
    print(f"每一行数据:{line}")

# 文件的关闭
f.close()

# with open 语法操作文件
with open("D:/桌面/python/test.txt", "r", encoding="UTF-8") as f:
    for line in f:
        print(f"每一行的数据{line}")

3. 文件的写入

f.open("文件路径", "w")
f.write()
# 内容刷新
f.flush()
  • 直接调用write,内容并未真正写入文件,但是会积攒在程序的内存中,也就是缓冲区
  • 当调用flush时候,内容才会被真正写入文件
  • 避免频繁操作硬盘

4. 文件的追加

f.open("文件路径", "a")
f.write()
# 内容刷新
f.flush()
  • a模式,文件不存在会创建文件
  • a模式,文件存在则会在最后追加文件

八. 异常

1. 了解异常

所谓异常就是BUG

2. 异常的捕获方法

捕获异常的作用:提前假设某处出现异常,做好提前准备,当真的出现异常的时候,可以有后续手段

捕获常规异常:

try:
    可能发生错误的代码
except:
    如果出现异常执行的代码

捕获指定的异常:

try:
    print(name)
except NameError as e:
    print('name变量名称未定义错误')

捕获多个异常:

try:
    print(1/0)
except (NameError,AeroDivisionError):
    print("")

异常else

try:
    print(1)
except Exception as e:
    print(e)
else
	print("我是else,是没有出现异常时执行的代码")

异常的finally:

try:
    ...
except Exception as e:
    ....
else:
    ...
finally:
    ....

3. 异常的传递

异常具有传递性

# 定义一个出现异常的方法
def func1():
    print("func1 开始执行")
    num = 1 / 0     # 除0 肯定有异常
    print("func1 结束执行")


# 定义一个无异常的方法,调用上面的方法
def func2():
    print("func2 开始执行")
    func1()
    print("func2 结束执行")


# 定义一个方法,调用前面的方法
def main():
    try:
        func2()
    except Exception as e:
        print(f"出现异常,异常信息是:{e}")


main()

4. Python模块

  • Python模块,是一个python文件,以.py结尾,模块能定义函数,类和变量,模块里也能包含可执行的代码

  • 模块的作用:

    • python中有很多各种不同的模块,每一个模块都能帮助我们实现一些功能,比如实现和时间相关的可以使用time模块。可以将模块看成一个工具包,每一个工具包都有各种不同的工具供我们使用而实现不同的功能
  • 模块的导入方式:

    [from 模块名] import [模块|| 变量 | 函数 | *][as 别名]
    
    • import 模块名
    • from 模块名 import 类、变量、方法等
    • from 模块名 import *
    • import 模块名 as 别名
    • from 模块名 import 功能名 as 别名
  • 自定义模块

5. Python包

  • 从物理上来看,包就是一个包含了一个init.py 文件的文件夹,该文件夹可以用于包含多个模块文件,从逻辑上来看,包的本质依旧是模块

  • 导入包

    import 包名.模块名
    包名.模块名.目标
    

6. 安装第三方包

pip install 包

pip install -i 镜像网站 包

九. 可视化综合案例(折线图)

10.1 json数据格式

JSON是一种轻量级的数据交互格式,可以按照JSON指定的格式去组织和封装数据

  • JSON本质上是一个带有特定格式的字符串

  • 在Python JSON要么是一个单独的字典或者内部元素都是字典的列表

  • 主要功能

    • 是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互
  • 各个编程语言存储数据的容器不尽相同,例如:在Python中有字典dict这样的数据类型而在其他语言中可能没有对应的字典。

    可以使用JSON数据格式作为数据中转站

  • json格式的数据要求很严格(字典)

    # 实例
    {"name":"admin", "age":18}
    
  • python数据和json数据的互相转换

    # 导入json模块
    import json
    
    # 准备符合格式json要求的python数据
    data = [{"name": "wang", "age":19},{"name": "li", "age":79}]
    
    # 通过json.dumps(data)方法把python数据转化为了json数据
    data = json.dumps(data)
    
    # 通过json.loads(data)方法把json数据转化为了python数据
    data = json.loads(data)
    

10.2 pyecharts模块的入门使用

导入

# 显示虚拟环境
conda env list
# 进入虚拟环境
conda activate 环境名
# 安装
pip install pyecharts
  • pyecharts入门:基础折线图

    # 导包,导入line功能构建折线图兑现
    from pyecharts.charts import Line
    
    # 得到折线图对象
    line = Line()
    
    # 添加x轴数据
    line.add_xaxis(["中国", "美国", "日本"])
    
    # 添加y轴数据
    line.add_yaxis("GDP",[30, 20 ,10])
    
    # 生成图表
    line.render()
    
  • pyecharts模块中有很对的配置选项,常用到2个类别的选项

    • 全局配置选项

      全局配置通过set_global_opts方法来进行配置,相应的选项

      TitleOpts 设置标题
      LegendOpts 图例配置项
      ToolboxOpts 工具箱配置项
      VisualMapOpts 视觉映射配置项
      TooltipOpts 提示框配置项
      DataZoomOpts 区域缩放配置项
    • 系列配置选项

10.3 数据处理

网站:ab173.com 查看json数据

10.4 折线图

  • 导入json
import json
  • 处理数据以美国为例
f_us = open("D:/桌面/折线图数据/美国.txt", "r", encoding="UTF-8")
us_data = f_us.read()   # 美国的全部内容
  • 规范化数据
# 去掉不和JSON规范的开头
us_data = us_data.replace("jsonp_1629344292311_69436(", "")
# 去掉和JSON规范的结尾
us_data = us_data[:-2]  # 使用切片去除最后一个不和规范的数据
  • JSON转python字典
us_dict = json.loads(us_data)
# 获取trend key
us_trend_data = us_dict['data'][0]['trend']
  • 获取x,y轴数据
# 获取日期数据,用于x轴,取2020年(到314结束)
us_x_data = us_trend_data['updateDate'][:314]

# 获取确认数据,用于y轴,取2020年(到314结束)
us_y_data = us_trend_data['list'][0]['data'][:314]
  • 生成图表
line = Line()       # 获取折线图对象
  • 添加x,y轴数据
line.add_xaxis(us_x_data)   # x轴是公用的,所以使用一个国家的数据即可

# label_opts=LabelOpts(is_show=False) 局部设置,数据不显示
line.add_yaxis("美国确诊人数", us_y_data, label_opts=LabelOpts(is_show=False))        

  • 生成图表
# 调用render方法
line.render()
# 关闭文件对象
f_us.close()
f_jp.close()
f_in.close()
  • 全局设置
line.set_global_opts(
    # 标题设置
    title_opts=TitleOpts(title="2020年美日印三国确证人数对比折线图", pos_left="center", pos_bottom="1%"),
    legend_opts=LegendOpts(is_show=True),
    toolbox_opts=ToolboxOpts(is_show=True),
    visualmap_opts=VisualMapOpts(is_show=True)
)
  • 完整示例
import json
from pyecharts.charts import Line
from pyecharts.options import TitleOpts, LabelOpts, LegendOpts, ToolboxOpts, VisualMapOpts
# 处理数据
f_us = open("D:/桌面/折线图数据/美国.txt", "r", encoding="UTF-8")
us_data = f_us.read()   # 美国的全部内容

f_jp = open("D:/桌面/折线图数据/日本.txt", "r", encoding="UTF-8")
jp_data = f_jp.read()   # 美国的全部内容

f_in = open("D:/桌面/折线图数据/印度.txt", "r", encoding="UTF-8")
in_data = f_in.read()   # 美国的全部内容

# 去掉不和JSON规范的开头
us_data = us_data.replace("jsonp_1629344292311_69436(", "")
jp_data = jp_data.replace("jsonp_1629350871167_29498(", "")
in_data = in_data.replace("jsonp_1629350745930_63180(", "")

# 去掉和JSON规范的结尾
us_data = us_data[:-2]  # 使用切片去除最后一个不和规范的数据
jp_data = jp_data[:-2]
in_data = in_data[:-2]

# JSON转python字典
us_dict = json.loads(us_data)
jp_dict = json.loads(jp_data)
in_dict = json.loads(in_data)
# print(type(us_dict))
# print(us_data)

# 获取trend key
us_trend_data = us_dict['data'][0]['trend']
jp_trend_data = jp_dict['data'][0]['trend']
in_trend_data = in_dict['data'][0]['trend']
# print(type(trend_data))
# print(trend_data)

# 获取日期数据,用于x轴,取2020年(到314结束)
us_x_data = us_trend_data['updateDate'][:314]
jp_x_data = jp_trend_data['updateDate'][:314]
in_x_data = in_trend_data['updateDate'][:314]
# print(x_data)

# 获取确认数据,用于y轴,取2020年(到314结束)
us_y_data = us_trend_data['list'][0]['data'][:314]
jp_y_data = jp_trend_data['list'][0]['data'][:314]
in_y_data = in_trend_data['list'][0]['data'][:314]

# 生成图表
line = Line()       # 获取折线图对象

# 添加x轴数据
line.add_xaxis(us_x_data)   # x轴是公用的,所以使用一个国家的数据即可

# 添加y轴数据
# label_opts=LabelOpts(is_show=False) 局部设置,数据不显示
line.add_yaxis("美国确诊人数", us_y_data, label_opts=LabelOpts(is_show=False))        # 添加美国的y轴数据
line.add_yaxis("日本确诊人数", jp_y_data, label_opts=LabelOpts(is_show=False))        # 添加日本的y轴数据
line.add_yaxis("印度确诊人数", in_y_data, label_opts=LabelOpts(is_show=False))        # 添加印度的y轴数据

# 设置全局选项
line.set_global_opts(
    # 标题设置
    title_opts=TitleOpts(title="2020年美日印三国确证人数对比折线图", pos_left="center", pos_bottom="1%"),
    legend_opts=LegendOpts(is_show=True),
    toolbox_opts=ToolboxOpts(is_show=True),
    visualmap_opts=VisualMapOpts(is_show=True)
)
# 调用render方法生成图表
line.render()
# 关闭文件对象
f_us.close()
f_jp.close()
f_in.close()

十. 地图

1. 基础地图使用

2. 疫情地图-国内疫情地图

3. 疫情地图-省级疫情地图

十一. 动态柱状图

1. 基础柱状图

通过Bar构建基础柱状图

2. 基础时间线柱状图

  • Timeline() 时间线

    柱状图描述的是分类数据,回答的是每一个分类中有多少这个问题,这是柱状图的主要特点,同时柱状图很难动态的描述一个趋势性的数据,pyecharts提供了一种解决方案- 时间线

  • 如果说Bar,Line对象是一张图标,时间线就是创建一个一维的x轴,轴上的每个点就是一个图表对象

# 导包
from pyecharts.charts import Timeline
timeline = TimeLine()
  • 自动播放
# 自动播放设置
timeline.add_schema(
    play_interval=1000,    # 自动播放的时间间隔,单位是毫秒
    is_timeline_show=True,  # 是否自动播放的时候显示时间线
    is_auto_play=True,      # 是否自动播放
    is_loop_play=True       # 是否循环自动播放
)
  • 设置主题
timeline = Timeline({"theme": ThemeType.ROMANTIC})

3. gdp动态柱状图绘制

  • 列表的sort方法

    列表.sort(key = 选择排序依据的函数, reverse = True|False)

    • 参数key:要求传入一个函数,表示将列表的每一个元素都传入函数中,返回排序的结果
    • 参数reverse,是否反转排序结果,True表示降序,False表示升序
from pyecharts.charts import Bar, Timeline
from pyecharts.options import *
from pyecharts.globals import ThemeType

# 读取数据
f = open("D:/桌面/python/资料/可视化案例数据/动态柱状图数据/1960-2019全球GDP数据.csv", "r", encoding="GB2312")
# .readlines() 打开是一个列表
data_lines = f.readlines()
# 关闭文件
f.close()
# 删除第一条数据
data_lines.pop(0)

# 将数据转化为字典存储
# 定义一个字典对象
# 格式为:{1960: [[美国, 123], [中国, 321]....], 1961:[[美国, 123], [中国, 321]....]......}
data_dict = {}
for line in data_lines:							
    year = int(line.split(",")[0])      # 年份
    country = line.split(",")[1]        # 国家
    gdp = float(line.split(",")[2])     # gdp数据
    # 数据格式化
    try:
        data_dict[year].append([country, gdp])
    # 如果没有key, 就捕获异常,新建一个列表
    except KeyError:
        data_dict[year] = []
        data_dict[year].append([country, gdp])

# print(data_dict)

# 创建时间线对象
# 设置颜色格式
timeline = Timeline({"theme": ThemeType.LIGHT})

# 排序年份
sorted_year_list = sorted(data_dict.keys())
for year in sorted_year_list:
    # 通过gdp进行排序
    data_dict[year].sort(key=lambda element: element[1], reverse=True)

    # 取出本年份前8名的国家
    year_data = data_dict[year][0:8]
    x_data = []
    y_data = []
    # for循环每一年的数据,基于每一年的数据,创建每一年的bar对象
    for country_gdp in year_data:
        x_data.append(country_gdp[0])   # x轴添加国家
        y_data.append(country_gdp[1] / 100000000)   # y轴添加gdp

    # 构建柱状图
    bar = Bar()
    # 调转x和y轴数据完成从大到小
    x_data.reverse()
    y_data.reverse()
    
    bar.add_xaxis(x_data)
    # 设置数值标签在右侧 label_opts=LabelOpts(position="right")
    bar.add_yaxis("GDP(亿)", y_data, label_opts=LabelOpts(position="right"))
    # 反转x,y轴
    bar.reversal_axis()
    
    # 设置每一年的图表的标题
    bar.set_global_opts(
        title_opts=TitleOpts(title=f"{year}年全球前八GDP数据")
    )
    
    # 在for中,将每一年的bar对象添加到时间线中
    timeline.add(bar, str(year))

# 设置时间线自动播放
timeline.add_schema(
    play_interval=1000,
    is_timeline_show=True,
    is_auto_play=True,
    is_loop_play=False
)

# 绘图
timeline.render("1960-2019全球GDP前八国家.html")

十二、面向对象

1. 初识对象

使用对象组织数据

在程序中是可以做到和生活中那样,设计表格、生产表格、填写表格的组织形式的

  • 在程序中设计表格,称之为:设计类(class)

    class Sudent:
        name = None		# 记录学生姓名
    
  • 在程序中打印生产表格,称之为:创建对象

    stu_1 = Student()	# 基于类创建对象
    
  • 在程序中填写表格,称之为:对象属性赋值

    stu_1.name = "胡图图"	# 为学生1对象赋予名称属性值
    

2. 成员方法

类的定义和使用语法

class 类名称:
    类的属性
    类的行为
  • class是关键字,表示要定义类了
  • 类的属性,即定义在类中的变量(成员变量)数据
  • 类的行为,即定义在类中的函数(成员方法)函数

创建类对象的语法

对象 = 类名称()

成员方法

在类中定义成员方法和定义函数基本一致

def 方法名(self, 形参1, ....形参n):
    方法体

self关键字是成员方法定义的时候,必须填写的

  • 它用来表示类对象自身的意思
  • 当我们使用类对象调用方法的时候,self会被python自动传入,在传参的时候可以忽略
  • 在方法内部,想要访问类的成员变量,必须使用self
# 定义一个带有成员方法的类
class Student:
    name = None  # 学生姓名

    def say_hi(self):
        print(f"大家好啊,我是{self.name},初次见面,请多关照")

    def say_hi2(self, msg):
        print(f"大家好,我是{self.name},{msg}")    # 想要访问成员属性,必须使用self关键字,外部传入参数则不需要


stu_1 = Student()
stu_1.name = "胡图图"
stu_1.say_hi()
stu_1.say_hi2("我的耳朵很大")

stu_2 = Student()
stu_2.name = "小美"
stu_2.say_hi()
stu_2.say_hi2("我最爱漂亮")

3. 类和对象

  • 类包含属性和行为,所以使用类描述现实世界事物是很合适的
  • 类相当于图纸,对象是基于图纸生产的具体实体
  • 面向对象编程就是,使用对象进行编程
# 设计一个闹钟类
class Clock:
    id = None
    price = None

    def ring(self):
        import winsound
        winsound.Beep(2000, 3000)


# 构建两个闹钟对象并使其工作
clock1 = Clock()
clock1.id = "2023"
clock1.price = 888
print(f"闹钟ID:{clock1.id}, 价格是:{clock1.price}")
clock1.ring()

clock2 = Clock()
clock2.id = "2024"
clock2.price = 888
print(f"闹钟ID:{clock2.id}, 价格是:{clock2.price}")
clock2.ring()

4. 构造方法

Python类可是使用

__init__(self,...)		# 构造方法

可以实现

  • 在创建类对象(构造类)的时候,会自动执行
  • 在创建类对象(构造类)的时候,将传入参数自动传递给init方法使用
class Student:
    # # 可以省略
    # name = None
    # age = None
    # tel = None

    def __init__(self, name, age, tel):
        self.name = name
        self.age = age
        self.tel = tel
        print("Student类创建了一个类对象")


stu = Student("胡图图", 6, "1111111111")
print(stu.name)
print(stu.age)
print(stu.tel)

5. 其他内置方法

内置的类方法,各自有其特殊的功能,称之为魔术方法

方法 作用
init 构造方法,可用于构建类对象的时候设置初始化行为
str 字符串方法,用于实现类对象转化字符串的行为
lt 用于两个类对象小于,大于符号比较
le 用于两个类对象小于等于,大于等于符号比较
eq 用于两个类对象== 符号比较
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # __str__魔术方法
    def __str__(self):
        return f"Student类对象, name{self.name}, age: {self.age}"

    # __lt__魔术方法
    def __lt__(self, other):
        return self.age < other.age

    # __le__魔术方法
    def __le__(self, other):
        return self.age <= other.age

    # __eq__魔术方法
    def __eq__(self, other):
        return self.age == other.age


stu1 = Student("胡图图", 6)
stu2 = Student("壮壮", 8)
stu3 = Student("小美", 6)

# __str__, 如果没有该方法,则输出内存地址
print(stu1)
print(str(stu1))

# __lt__,直接对两个对象进行比较是不可以的,但是在类中实现__lt__方法
# 即可同时完成:小于符号和大于符号两种比较
print(stu1 < stu2)
print(stu1 > stu2)

# __le__
print(stu1 <= stu3)

# __eq__
print(stu1 == stu3)

6. 封装

封装:将现实世界事物在类中描述为属性和方法,即为封装

面向对象包含三大特性:

  • 封装
  • 继承
  • 多态

私有成员:现实世界有部分属性和行为不公开对使用者开放,同样在类中描述属性和方法的时候也需要达到这个要求,就需要定义私有成员了

类中提供了私有成员的形式来支持

  • 私有成员变量
  • 私有成员方法

定义私有成员的方式:

# 私有成员变量
__变量名
# 私有成员方法
def __方法名:
  • 私有方法无法直接被类对象使用
  • 私有变量无法赋值,也无法获取值

私有成员的访问权限

  • 类对象无法访问私有成员
  • 类中的其他成员可以访问私有成员
# 设计一个类,用来描述手机
class Phone:
    # 提供私有成员变量:__is_5g_enable
    __is_5g_enable = True      # 5g状态

    # 提供私有成员方法:__check_5g()
    def __check_5g(self):
        if self.__is_5g_enable:
            print("5g开启")
        else:
            print("5g关闭,使用4g网络")

    # 提供公开成员方法:call_by_5g()
    def call_by_5g(self):
        self.__check_5g()
        print("正在通话中")


phone = Phone()
phone.call_by_5g()

7. 继承

class 类名(父类名):
    类内容体

继承可以分为单继承和多继承

多继承:

Python的类之间也支持多继承,即一个类,可以继承多个父类

class 类名(父类1,父类2....父类N):
    类内容体

多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级

即:先继承的保留,后继承的被覆盖

pass关键字:占位语句,补全代码,无实义

8. 复写父类成员方法和调用父类成员

  • 复写:子类继承父类的成员方法后,如果对其不满意,可以进行复写

    即:在子类中重新定义同名的属性或方法即可

class Phone:
    IMEI = None
    producer = "hututu"

    def call_by_5g(self):
        print("使用5g通话")


# 定义子类,复写父类成员
class MyPhone(Phone):
    producer = "xiaomei"        # 复写父类的成员属性

    def call_by_5g(self):
        print("开启CPU单核模式,确保通话的时候省电")
        print("使用5g网络进行通话")
        print("关闭CPU单核模式,确保性能畅通")


phone = MyPhone()
phone.call_by_5g()
print(phone.producer)

调用父类同名成员

一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员,如果需要使用被复写的父类的成员,需要特殊的调用方法:

# 调用父类成员
父类名.成员变量
父类名.成员方法(self)

# 使用super()调用父类成员
super().成员变量
super().成员方法()
  • 注意:只可以在子类内部调用父类的同名成员,子类的实体类对象调用默认是调用子类复写的

9. 类型注解

9.1 变量的类型注解

Python在3.5版本的时候就引入了类型注解,以方便静态类型检查工具,IDE等第三方工具

**类型注解:**在代码中设计数据交互的地方,提供数据类型的注解

主要功能:

  • 帮助第三方IDE工具(PCharm)对代码进行类型推断,协助做代码提示
  • 帮助开发者自身对变量进行类型注释

支持:

  • 变量的类型注解
  • 函数(方法)形参列表和返回值的类型注解

变量注解的语法:

变量:类型
#type:类型
  • 元组类型设置类型详细注解,需要将每一个元素都标记出来
  • 字典类型设置类型详细注解,需要2个类型,第一个key,第二个value
# 基本数据类型注解
import json
import random
from typing import List, Tuple, Dict

var_1: int = 10
var_2: str = "hututu"
var_3: bool = True


# 类对象类型注解
class Student:
    pass


stu: Student = Student()

# 基本容器类型注解
my_list: list = [1, 2, 3]
my_tuple: tuple = (1, 2, 3)
my_dict: dict = {"胡图图": 99}

# 容器类型详细注解
my_list1: List[int] = [1, 2, 3]
my_tuple1: Tuple[int, str, bool] = (1, "hututu", True)
my_dict1: Dict[str, int] = {"胡图图": 99}

# 在注释中进行类型注解
# alt+enter 自动导包
var_11 = random.randint(1, 10)  # type: int
var_12 = json.loads('{"name": "胡图图"}')  # type: dict[str, str]


def fun():
    return 10


var_13 = fun()  # type: int
  • 类型注解只是提示性的,并非决定性,数据类型和注解类型无法对应也不会导致错误

9.2 函数和方法的类型注解

函数(方法)的类型注解-形参注解语法:

def 函数方法名(形参名:类型,形参名:类型....):
    pass

函数方法的类型注解-返回值注解语法:

def 函数方法名(形参名:类型,形参名:类型....) ->返回值类型:
	pass
# 对形参进行类型注解
def add(x: int, y: int):
    return x + y


add(1, 2)


# 对返回值进行类型注解
def fun(data: list) -> list:
    return data


fun([1, 2, 3])

9.3 Union类型注解

可以定义联合类型注解

Union[类型,....,类型]
# 使用Union必须先导包
from typing import Union, List

my_list: List[Union[int, str]] = [1, 2, "hututu", "xiaomei"]


def func(data: Union[int, str]) -> Union[int, str]:
    pass

10. 多态

  • 多态:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态

    即:同样的行为(函数),传入不同的对象,得到不同的状态

  • 多态常用于继承关系上

  • 抽象类(接口):含有抽象方法(方法体是空实现的[pass])的类

    抽象类相当于定义一个标准,包含了一些抽象的方法,要求子类必须实现

    抽象类的作用:做顶层实际标准,以便子类做具体实现,也是对子类的一种软性约束,要求子类必须复写父类的一些方法,并配合多态使用,获得不同的工作状态。

# 演示抽象类
class AC:
    def cool_wind(self):
        """制冷"""
        pass

    def hot_wind(self):
        """制热"""
        pass

    def swing_l_r(self):
        """左右摆风"""
        pass


# 子类
class Midea_AC(AC):
    def cool_wind(self):
        print("美的空调制冷的具体实现")

    def hot_wind(self):
        print("美的空调制热的具体实现")

    def swing_l_r(self):
        print("美的空调左右摆风的具体实现")


# 具体类的实现
class GREE_AC(AC):
    def cool_wind(self):
        print("格力空调制冷的具体实现")

    def hot_wind(self):
        print("格力空调制热的具体实现")

    def swing_l_r(self):
        print("格力空调左右摆风的具体实现")


def make_cool(ac: AC):
    ac.cool_wind()


midea_ac = Midea_AC()
gree_ac = GREE_AC()

make_cool(midea_ac)
make_cool(gree_ac)

11. 综合案例

data_define.py

"""
数据定义的类
"""


class Record:

    def __init__(self, data, order_id, money, province):
        self.data = data  # 订单日期
        self.order_id = order_id  # 订单ID
        self.money = money  # 订单金额
        self.province = province  # 销售省份

    # 控制输出为字符串而不是内存地址
    def __str__(self):
        return f"{self.data}, {self.order_id}, {self.money}, {self.province}"

file_define.py

"""
和文件相关的类定义
"""
import json
from typing import List

from data_define import Record


# 先定义一个抽象类用来做顶层设计,确定有哪些功能需要实现
class FileReader:

    def read_data(self) -> List[Record]:
        """读取文件的数据,将读取的每一条数据都转化为Record对象,将他们都封装到list内返回即可"""
        pass


class TextFileReader(FileReader):
    def __init__(self, path):
        self.path = path  # 定义成员变量记录文件的路径

    # 复写(实现抽象方法)父类的方法
    def read_data(self) -> List[Record]:
        f = open(self.path, "r", encoding="UTF-8")

        record_list: List[Record] = []
        for line in f.readlines():
            line = line.strip()  # 消除读取到的每一行数据中的\n
            # print(line)
            data_list = line.split(",")
            record = Record(data_list[0], data_list[1], int(data_list[2]), data_list[3])
            record_list.append(record)

        f.close()
        return record_list


class JsonFileReader(FileReader):
    def __init__(self, path):
        self.path = path  # 定义成员变量记录文件的路径

    def read_data(self) -> List[Record]:
        f = open(self.path, "r", encoding="UTF-8")

        record_list: List[Record] = []
        for line in f.readlines():
            # 将json数据类型转化为字典数据类型
            data_dict = json.loads(line)
            record = Record(data_dict["date"], data_dict["order_id"], int(data_dict["money"]), data_dict["province"])
            record_list.append(record)
        f.close()
        return record_list


# 测试
if __name__ == '__main__':
    # text_file_reader = TextFileReader("D:/桌面/python/资料/2011年1月销售数据.txt")
    json_file_reader = JsonFileReader("D:/桌面/2011年2月销售数据JSON.txt")
    # text_file_reader.read_data()
    list2 = json_file_reader.read_data()
    for l in list2:
        print(l)

main.py

"""实现步骤:
1. 设计一个类,可以完成数据的封装
2. 设计一个抽象类,定义文件读取的相关功能,并使用子类实现具体功能
3. 读取文件,生产数据对象
4. 进行数据需求的逻辑计算(计算每一天的销售额)
5. 通过PyEcharts进行图形绘制
"""
from typing import List

from file_define import FileReader, TextFileReader, JsonFileReader
from data_define import Record
from pyecharts.charts import Bar
from pyecharts.options import *
from pyecharts.globals import ThemeType

text_file_reader = TextFileReader("D:/桌面/python/资料/2011年1月销售数据.txt")
json_file_reader = JsonFileReader("D:/桌面/2011年2月销售数据JSON.txt")

jan_data: List[Record] = text_file_reader.read_data()
feb_data: List[Record] = json_file_reader.read_data()

# 将2个月份的数据合并为1个list来存储
all_data: List[Record] = jan_data + feb_data

# 开始进行数据计算
# key:日期, value:当天营业额
data_dict = {}
for record in all_data:
    if record.data in data_dict.keys():
        # 当前日期已经有记录了,所以和老记录累加即可
        data_dict[record.data] += record.money
    else:
        data_dict[record.data] = record.money

# print(data_dict)

# 可视化图表开发
bar = Bar(init_opts=InitOpts(theme=ThemeType.LIGHT))

bar.add_xaxis(list(data_dict.keys()))   # 添加x轴数据
# label_opts=LabelOpts(is_show=False) 不显示数据
bar.add_yaxis("销售额", list(data_dict.values()), label_opts=LabelOpts(is_show=False))  # 添加y轴数据

bar.set_global_opts(
    title_opts=TitleOpts(title="每日销售额")
)

bar.render("每日销售额柱状图.html")

python从入门到入土_第1张图片

十三、SQL语言

1. SQL基础和DDL

  • SQL:结构化查询语言,用于访问和处理数据库的标准计算机语言

  • 由于数据库管理系统的功能非常多,不仅仅是存储数据,还要包含:数据的管理、表的管理、库的管理、账户管理、权限管理

    SQL分为以下几类

    名称 作用
    DDL(数据定义语言) 库的创建删除、表的创建删除
    DML(数据操纵语言) 新增数据、删除数据、修改数据
    DCL(数据控制语言) 新增用户、删除用户、密码修改、权限管理
    DQL(数据查询语言) 基于需求查询和计算数据
  • SQL特点

    • 大小写不敏感

    • 以; 作为结束

    • 支持注释

      --单行注释
      # 单行注释
      /*多行
      注释*/
      
  • DDL-库管理

    要求 语句
    查看数据库 show databases;
    使用数据库 use 数据库名称;
    创建数据库 create database 数据库名称 [charset UTF-8];
    删除数据库 drop database 数据库名称;
    查看当前使用的数据库 select database();

    DDL-表管理

    要求 语句
    查看哪些表 show tables;
    删除表 drop table if exists 表名称;
    创建表 create table 表名称( 列名称 列类型;…);
-- 列类型有
int 
float
varchar
date
timestamp

2. DML

关键字 作用
insert 插入
delete 删除
update 更新

数据插入insert

insert into[(1,2.....,列N)] 
values[(1,.....值N),
      (1,.....值N),
      ......]

数据删除delete

delete from 表名称
where	条件判断

数据更行update

update 表名
set=where 	判断语句

3. DQL

3.1 基础查询

在SQL中,通过select关键字开头的SQL语句,进行数据的查询

select 字段列表
from

3.2 group by 进行分组聚合查询

select 字段|聚合函数
fromwhere 判断条件
group by
  • 聚合函数
函数名 作用
sum(列) 求和
avg(列) 求平均值
min(列) 求最小值
max(列) 求最大值
count(列|*) 求数量

3.3 排序分页

结果排序

select|聚合函数|*
fromwhere 判断语句
group by 
order by		[ASC,DESC]

结果分页限制:使用limit关键字,对查询结果进行数量限制或者分页显示

select|聚合函数|*
fromwhere 判断语句
group by 
order by		[ASC,DESC]
limit n[,m]

4. python操作mysql基础使用

安装第三方库

pip install pymysql
  • 创建MySql的数据库链接
from pymysql import Connection
# 创建到mysql数据库的链接
conn = Connection(
    host="localhost",   # 主机名(IP)
    port=3306,          # 端口
    user="root",        # 账户
    password="******" # 密码
)

# 关闭链接
conn.close()
  • 执行非查询性质的sql语句
# 执行非查询性质SQL
cursor = conn.cursor()  # 获取到游标对象
# 选择数据库
conn.select_db("test")
# 执行sql
cursor.execute("create table test_pymysql(id int);")
  • 执行查询性质的sql语句
# 执行查询性质SQL
cursor = conn.cursor()  # 获取到游标对象
# 选择数据库
conn.select_db("world")
# 执行sql
cursor.execute("select * from student")		

results = cursor.fetchall()     # 返回一个大元组
for r in results:
    print(r)

5. Python操作MySql数据插入

  • pymysql库在执行对数据库有修改操作的行为时,是需要通过链接对象的commit或者成员方法来进行确认的

手动commit

from pymysql import Connection

# 构建到Mysql数据库的链接
conn = Connection(
    host="localhost",
    port=3306,
    user="root",
    password="******"
)

# 执行非查询性质的SQL
# 获取到游标对象
cursor = conn.cursor()
# 选择数据库
conn.select_db("world")
# 执行sql语句
cursor.execute("insert into student values(7,'牛爷爷',79)")
# 通过commit确认
conn.commit()
# 关闭链接
conn.close()

自动commit

# 构建到Mysql数据库的链接
conn = Connection(
    host="localhost",
    port=3306,
    user="root",
    password="******",
    autocommit=True
)

6. 综合案例

  • DDL定义

    • 本次需要新建一个数据库来使用,数据库名称:py_sql

      create database py_sql charset utf8;
      
    • 基于数据结构,得到建表语句

      create table orders(
      	order_date date,
          order_id Varchar(255),
          money int,
          province varchar(10)
      );
      
  • 实现

    # 构建MySQL链接对象
    conn = Connection(
        host="localhost",
        port=3306,
        user="root",
        password="******",
        autocommit=True
    )
    # 获得游标对象
    cursor = conn.cursor()
    # 选择数据库
    conn.select_db("py_sql")
    # 组织SQL语句
    for record in all_data:
        sql = f"insert into orders(order_date,order_id,money,province) " \
              f"values('{record.data}', '{record.order_id}', {record.money},'{record.province}')"
        # print(sql)
        # 执行sql语句
        cursor.execute(sql)
    
    # 关闭链接对象
    conn.close()
    

你可能感兴趣的:(Python,python,开发语言)