Python学习笔记

Python

大小写敏感

常用数据类型

  • Python中常用的有6种值(数据)的类型
    • 数字(Number)
      • 整数(int),如:10、-10
      • 浮点数(float)
      • 复数(complex),如 4+3j, 以j结尾表示复数
      • 布尔(bool)表达现实生活中的逻辑,即真和假布尔(bool)True表示真False表示假。
    • 字符串(String)
      • 描述文本的一种数据类型
      • 字符串(string)由任意数量的字符组成
    • 列表(List)
      • 有序的可变序列
      • Python中使用最频繁的数据类型,可有序记录一堆数据
    • 元组(Tuple)
      • 有序的不可变序列
      • 可有序记录一堆不可变的Python数据集合
    • 集合(Set)
      • 无序不重复集合
      • 可无序记录一堆不重复的Python数据集合
    • 字典(Dictionary)
      • 无序Key-Value集合
      • 可无序记录一堆Key-Value型的Python数据集合

标识符:

1
2
3
4
5
6
FalseTrueNoneandasassert
breakclasscontinuedefdelelif
elseexceptfinallyforfromglobal
ifimportinislambdanonlocal
notorpassraisereturntry
whilewithyield

运算符

运算符
描述
实例
+
-
*两数相乘 或 返回一个被重复若干次的字符串
/
//取整除返回商的整数部分 9//2 输出结果:4 9.0//2.0 输出结果:4.0
%取余返回出发的余数
**指数a**b 为10的20次方 输出结果:10000000000000000000
//=
%=
**=

字符串

引号使用

# 单引号定义法,使用单引号进行包围
name = '黑马程序员'print (type (name))
# 双引号定义法name = "黑马程序员"
# print (type (name))
#三引号定义法,写法和多行注释是一样的
"""
name
我是
马程序员
"""
print (type (name))
  • +号拼接字符串

  • 通过占位符拼接

    # 通过占位的形式,完成拼接
    name = "黑马程序员"
    message = "学IT来: %s" % name 
    print (message)
    
    name = "传智播客"
    setup_year = 2006
    stock_price = 19.99
    message = "%s,成立于: %d,我今天的股价是: %f" % (name, setup_year, stock_price)
    print (message)
    
  • 字符串格式化 %d %s %f %5d %5.2f %.2f

  • 字符串格式化 快速写法

    """
    演示第二种字符串格式化的方式:f"{占位}
    """
    name = "传智播客"
    set_up_year = 2006
    stock_price = 19.99
    # f: format
    print(f"我是{name},我成立于:{set_up_year}年,我今天的股价是:{stock_price}")
    
  • 格式化表达式

    • f"(表达式)"
    • “%s%d%f” % (表达式、表达式、表达式)
  • input()

判断语句
  • if

    • 判断语句的结果,必须是布尔类型
      • True或FalseTrue会执行if内的代码语句
      • False则不会执行
    • 归属于if判断的代码语句块,需在前方填充4个空格缩进
    • Python通过缩进判断代码块的归属关系。
    if 条件:
      成立时要做的事
      成立时要做的事
    成不成立都做的事
    if a > b:
      a - b  
    
    
    • 提示,通过如下代码,可以定文一个变量num,变量内存储随机数字。
      python import random num= random.randint(1, 10)
  • while

      while 条件:
          条件满足时,做的事情1
          条件满足时,做的事情2
          条件满足时,做的事情3
          ...(省略)...
          只要条件满足会无限循环执行
    
  • for

    • 语法格式
      for 临时变量 in 待处理数据集(序列):
          循环满足条件时执行的代码
      
    • 注意点
      • 无法定义循环条件,只能被动取出数据处理
      • 要注意,循环内的语句,需要有空格缩进
    • 遍历字符串
     # 定义字符串 name 
     name ="itheima"
     # for循环处理字符串
     for x in name:
         print(×)
    
  • range

    • range(num)
      • 获取一个从0开始,到num结束的数字序列(不含num本身)
      • 如range(5)取得的数据是: [0,1,2,3,4]
    • range(num1, num2)
      • 获得一个从num1开始,到num2结束的数字序列(不含num2本身)
      • 如,range(5, 10)取得的数据是:[5,6,7,8, 9]
    • range(num1, num2, step)
      • 获得一个从num1开始,到num2结束的数字序列(不含num2本身)
      • 数字之间的步长,以step为准(step默认为1)
      • 如,range(5,10, 2)取得的数据是:[5,7,9]
函数
  • 函数的定义
def 函数名(传入参数):
    函数体
    return 返回值

def say_hi():
    print("我是你爸爸!")

容器

列表 list
  • 可以容纳多个元素(上限为2**63-1、9223372036854775807个)
  • 可以容纳不同类型的元素(混装)
  • 数据是有序存储的(有下标序号)
  • 允许重复数据存在
  • 可以修改(增加或删除元素等)
元组 tuple
  • 可以容纳多个数据
  • 可以容纳不同类型的数据(混装)
  • 数据是有序存储的(下标索引)
  • 允许重复数据存在
  • 一旦定义完成,不可以修改(增加或删除元素等)
  • 支持for循环
  • 元组定义: 定义元组使用小括号,且使用逗号隔开各个数据,数据可以是不同的数据类型。
    #定义元组字面量
    (元素, 元素, ... , 元素) 
    # 定义元组变量
    变量名称 = (元素, 元素,, 元素)
    # 定义空元组
    变量名称 = ()        #方式1
    变量名称 = tuple()  #方式2
    
  • .index()
  • .count()
  • .len(元组)
字符串
  • 作为数据容器,字符串有如下特点:
    • 只可以存储字符串
    • 长度任意(取决于内存大小)
    • 支持下标索
    • 引允许重复字符串存在
    • 不可以修改(增加或删除元素等)
    • 支持for循环
  • 字符串的替换
    • 语法: 字符串.replace(字符串1,字符串2)
    • 功能:将字符串内的全部:字符串1,替换为字符串2
    • 注意:不是修改字符串本身,而是得到了一个新字符串哦
操作说明
字符串[下标]根据下标索引取出特定位置字符
字符串.index(字符串)查找给定字符的第一个匹配项的下标
字符串.replace(字符串1,字符串2)将字符串内的全部字符串1,替换为字符串2
不会修改原字符串,而是得到一个新的
字符串.split(字符串)按照给定字符串,对字符串进行分隔
不会修改原字符串,而是得到一个新的列表
字符串.strip()
字符串.strip(字符串)
移除首尾的空格和换行符或指定字符串
字符串.count(字符串)统计字符串内某字符串的出现次数
len(字符串)统计字符串的字符个数
序列
  • 序列支持切片,即:列表、元组、字符串,均支持进行切片操作
  • 切片:从一个序列中,取出一个子序列
  • 语法:序列[起始下标:结束下标:步长]
    • 表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列:
    • 起始下标表示从何处开始,可以留空,留空视作从头开始
    • 结束下标(不含)表示何处结束,可以留空,留空视作截取到结尾
    • 步长表示,依次取元素的间隔
      • 步长1表示,一个个取元素
      • 步长2表示,每次跳过1个元素取
      • 步长N表示,每次跳过N-1个元素取
      • 步长为负数表示,反向取(注意,起始下标和结束下标也有反向标记)
    • 步长默认是1, 所以可以省略不写
      • 序列[n:m]
    • 起始和结束不写表示从头到尾,步长为1可以省略
      • 序列[:]
    • 起始和结束不写表示从头到尾,步长为n
    • 序列[::n]
    • 倒序切片取出n到m
      • 序列[::-1][n:m]
    • 切片取出n到m后倒序
      • 序列[n:m][::-1]
集合
  • 和列表、元组、字符串等定义基本相同:
    • 列表:[]
    • 元组:()
    • 字符串:“”
    • 集合:{}
  • 首先,因为集合是无序的,所以集合不支持:下标索引访问
  • 但是集合和列表一样,是允许修改的,所以我们来看看集合的修改方法。
  • 基本语法:
    # 定义集合字面量。
    {元素, 元素, ..., 元素}
    # 定义集合变量
    变量名称 = {元素, 元素, ..., 元素}
    #定义空集合
    变量名称 = set()
    
    • 添加新元素
      • 语法:集合.add(元素)
      • 结果:集合本身被修改,添加了新元素
    • 移除元素
      • 语法:集合.remove(元素)
      • 结果:集合本身被修改,移除了指定元素
    • 从集合中随机取出元素
      • 语法:集合.pop()
      • 结果:会得到一个元素的结果。同时集合本身被修改,元素被移除
    • 清空集合
      • 语法:集合.clear()
      • 结果:集合本身被清空
    • 取出2个集合的差集(集合1有而集合2没有的)
      • 语法:集合1.difference(集合2)
      • 结果:得到一个新集合,集合1和集合2不变
    • 消除两个集合的差集
      • 功能:对比集合1和集合2,在集合1内,删除和集合2相同的元素。
      • 语法:集合1.difference_update(集合2)
      • 结果:集合1被修改,集合2不变
    • 2个集合合并为1个
      • 语法:集合1.union(集合2)
      • 结果:得到新集合,集合1和集合2不变
    • 统计集合元素数量
      • 语法:len(集合)
      • 结果:得到集合的元素数量
    • 集合的遍历
      • 集合不支持下标索引,不能用while循环
      • 可以用for循环
        set1 = {1,2,3,4,5,6}
        for element in set1:
            printf(f"合集的元素有:{element}")
        
字典

key:value

  • 定义
    • 定义字典字面量
      • {key: value, key: value, key: value}
    • 定义字典变量
      • my_dict = {key: value, key: value, key: value}
    • 定义空字典
      • my_dict = {} 空字典定义方式1
      • my_dict = dict() 空字典定义方式2
    • 从字典中基于Key获取Value
      • my_dict[Key]
    • 字典嵌套
  • 语法
    • 新增元素
      • 语法:字典[Key]=Value
      • 结果:字典被修改,新增了元素
    • 更新元素
      • 语法:字典[Key] = Value
      • 结果:字典被修改,元素被更新
      • 注意:字典Key不可以重复,所以对已存在的Key执行上述操作,就是更新Value值
    • 删除元素
      • 语法:字典:pop(Key)
      • 结果:获得指定Key的Value,同时字典被修改,指定Key的数据被删除
    • 清空字典
      • 语法:字典.clear()
      • 结果:字典被修改,元素被清空
    • 获取全部Key
      • 语法:字典.keys()
      • 结果:得到字典中的全部Key
    • 遍历字典
      # 方式1:通过获取到全部的key来完成遍历
      for key in keys:
          printf(f"字典的key是:{key}")
          printf(f"字典的value是:{my_dict[key]}")
      
      # 方式2:直接对字典进行for循环,每一次循环都是直接得到key
      for key in my_dict:
          print(f"2字典的key是:{key}")
          print(f"字典的value是: {my_dict[key]}")
      
    • 统计字典内的元素数量
      • 语法:len(字典)
      • 结果:得到字典内的元素数量
数据容器分类
  • 是否支持下标索引
    • 支持:列表、元组、字符串 - 序列类型
    • 不支持:集合、字典 - 非序列类型
  • 是否支持重复元素:
    • 支持:列表、元组、字符串 - 序列类型
    • 不支持:集合、字典 - 非序列类型
  • 是否可以修改
    • 支持:列表、集合、字典
    • 不支持:元组、字符串
列表元组字符串集合字典
元素数量支持多个支持多个支持多个支持多个支持多个
元素类型任意任意仅字符任意Key: Value
Key:除字典外任意类型
Value:任意类型
下标索引支持支持支持不支持不支持
重复元素支持支持支持不支持不支持
可修改性支持不支持不支持支持支持
数据有序
使用场景可修改、可重复的一批数据记录场景不可修改、可重复的一批数据记录场景一串字符的记录场景不可重复的数据记录场景以Key检索Value的数据记录场景
数据容器的通用操作
  • 遍历
    • 5类数据容器都支持for循环遍历
    • 列表、元组、字符串支持while循环,集合、字典不支持(无法下标索引)
    • 尽管遍历的形式各有不同,但是,它们都支持遍历操作。
  • len()元素个数
  • max()最大元素
  • min()最小元素
  • 类型转换
    • list()容器转列表
    • tuple()容器转元组
    • str()容器转字符串
    • set()容器转集合
    • 无法转字典
  • sorted()容器排序
  • sorted(对象, reverse=True)容器反向排序

函数

函数多返回值
# 如果一个函数要有多个返回值,该如何书写代码?
def test_return():
    return 1, 2

x, y = test_return()
print(x)  # 结果1
print(y)  # 结果2
# 按照返回值的顺序,写对应顺序的多个变量接收即可
# 变量之间用逗号隔开
# 支持不同类型的数据return
函数多种传参方式

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

  • 位置参数
    • 调用函数时根据函数定义的参数位置来传递参数
    • 注意:传递的参数和定义的参数的顺序及个数必须一致
  • 关键字参数
    • 函数调用时通过“键=值”形式传递参数.
    • 作用:可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求.
    • 注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序
  • 缺省参数
    • 缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用).
    • 作用:当调用函数时没有传递参数,就会使用默认是用缺省参数对应的值
    • 注意:函数调用时,如果为缺省参数传值则修改默认参数值,否则使用这个默认值
  • 不定长参数
    • 不定长参数也叫可变参数.用于不确定调用的时候会传递多少个参数(不传参也可以)的场景.
    • 作用:当调用函数时不确定参数个数时,可以使用不定长参数
    • 不定长参数的类型:
      • 位置传递
        • 注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple), args是元组类型,这就是位置传递
          # 不定长 - 位置不定长,*号
          # 不定长定义的形式参数会作为元组存在,接收不定长数量的参数传入
          def user_info(*args):
              print(f"args参数的类型是: {type(args)}, 内容是:{args}")
          user_info(1, 2,3, '小明','男孩')
          
      • 关键字传递
        • 注意:参数是“键=值”形式的形式的情况下,所有的“键=值”都会被kwargs接受,同时会根据“键=值”组成字典.
          # 不定长 - 关键字不定长,**号
          def user_info(**kwargs):
              print(f"args参数的类型是: {type(kwargs)},内容是: {kwargs}")
              user_info(1, 2, 3, '小明', '男孩')
          
  • 函数参数
    • 这是一种,计算逻辑的传递,而非数据的传递。
    • 就像上述代码那样,不仅仅是相加,相见、相除、等任何逻辑都可以自行定义并作为函数传入。
      # 如下代码:
      def test_fundcompute:
          result = compute(1, 2) 
          print(result)
      def compute(x, y):
          return x + y
      test_func(compute)# 结果:3
      
      # 函数compute,作为参数,传入了test_func函数中使用。
      # test_func需要一个函数作为参数传入,这个函数需要接收2个数字进行计算,计算逻辑由这个被传入函数决定
      # compute函数接收2个数字对其进行计算,compute函数作为参数,传递给了test_func函数使用
      # 最终,在test_func函数内部,由传入的compute函数,完成了对数字的计算操作
      
匿名函数

函数的定义中

  • def关键字,可以定义带有名称的函数
  • lambda关键字,可以定义匿名函数(无名称)
  • 有名称的函数,可以基于名称重复使用。
  • 无名称的匿名函数,只可临时使用一次。

匿名函数定义语法:

  • lambda 传入参数:函数体(一行代码)
    • lambda 是关键字,表示定义匿名函数
    • 传入参数表示匿名函数的形式参数,如: x,y表示接收2个形式参数
    • 函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码

注意事项:

  • 匿名函数用于临时构建一个函数,只用一次的场景
  • 匿名函数的定义中,函数体只能写一行代码,如果函数体要写多行代码,不可用lambda匿名函数,应使用def定义带名函数

文件

  • mode常用的三种基础访问模式

    • r
      • 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
    • w
      • 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,原有内容会被删除。如果该文件不存在,创建新文件。
    • a
      • 打开一个文件用于追加。如果该文件已存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
  • open()

    • 在Python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下
    • open(name, mode, encoding)
      • name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。
      • mode:设置打开文件的模式(访问模式):只读、写入、追加等。
      • encoding:编码格式(推荐使用UTF-8)
    • 注意:此时的f是open函数的文件对象,对象是Python中一种特殊的数据类型,拥有属性和方法,可以使用对象.属性或对象.方法对其进行访问,后续面向对象课程会给大家进行详细的介绍。
  • read()

    • num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。
  • readlin()

    • 一次读取一行内容
  • readlines()

    • readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
  • close()

    • 关闭文件占用
    • 内置了flush()的功能
  • with open() as f

    • 会自动将文件关闭
  • write()

    • 直接调用write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区
    • 当调用flush的时候,内容会真正写入文件
    • 这样做是避免频繁的操作硬盘,导致效率下降(攒一堆,一次性写磁盘)
  • flush()

    • 将内存中积攒的内容,写入到硬盘中

异常

异常捕获

  • 捕获异常
    try:
        可能发生错误的代码
    except:
        如果出现错误执行的代码
    
  • 捕获指定异常
    try:
        print(name)
    except NameError as e:
        print("出现了变量未定义的异常")
        print(e)
    
  • 捕获多个异常
    try:
        print(name)
    except(NameError, ZeroDivisionError):
        print"出现了变量未定义 或者 除以0的异常错误"
  • 捕获所有异常
    try:
        f = open("D:/123.txt","r",encoding="UTF-8")
    except Exception as e:
        print"出现异常")
        f =  open("D:/123.txt","w",encoding="UTF-8")
    else:
        print("没有异常")
    finally:
        f.close()
    
  • finally
    • 有无异常都执行

异常传递

    # 异常在func01中没有被捕获
def func01(): 
    print("这是func01开始")
    num = 1 /0
    print("这是func01结束")
    
    # 异常在func02中没有被捕获
def func02():
    print("这是func02开始")
    func01()
    print("这是func02结束")

    # 异常在mian中被捕获
def main(): 
    try:
        func02()
    except Exception as e: 
        print(e)
        
main()
  • 异常是具有传递性的
    • 当函数func01中发生异常,并且没有捕获处理这个异常的时候,异常会传递到函数func02,当func02也没有捕获处理这个异常的时候main函数会捕获这个异常, 这就是异常的传递性.
    • 提示:当所有函数都没有捕获异常的时候,程序就会报错

模块

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

  • 模块的作用: python中有很多各种不同的模块,每一个模块都可以帮助我们快速的实现一些功能,比如实现和时间相关的功能就可以使用time模块我们可以认为一个模块就是一个工具包,每一个工具包中都有各种不同的工具供我们使用进而实现各种不同的功能.

  • 大白话:模块就是一个Python文件,里面有类、函数、变量等,我们可以一拿过来用(导入模块去使用)

  • 模块的导入方式模块在使用前需要先导入 导入的语法如下:

    • [from 模块名] import [模块 | 类| 变量 | 函数 | *] [as 别名]
    • 常用的组合形式如:
      • import 模块名
      • from 模块名 import 类、变量、方法等
      • from 模块名 import *
      • import 模块名 as 别名
      • from 模块名 import 功能名 as 别名
    • import 模块名
    • 基本语法:
      • import 模块名
      • import 模块名1,模块名2
      • 模块名.功能名()
    • as定义别名:
      • 基本语法:
        • 模块定义别名
          • import 模块名 as 别名
        • 功能定义别名
          • from 模块名 import 功能 as 别名
      #导入时间模块
      import time
      print("开始")
      #让程序睡眠1秒(阻塞)
      time.sleep(1)
      print("结束")
      
      # 使用from导入time的sleep功能(函数)
      from time import sleep
      print("你好") 
      sleep(5) 
      print("我好") 
      
      # 使用 * 导入time 模块的全部功能 
      from time import * # *表示全部的意 
      print("你好")
      sleep(5) 
      print("我好")
      
      # 使用as给特定功能加上别名 
      import time as t
      print("称好") 
      t.sleep(5) 
      print("我好")
      
      from time import sleep as sl
      print("称好") 
      sl(5) 
      print("我好")
      
  • 自定义模块

    • 在Python代码文件中正常写代码即可,通过import、from关键字和导入Python内置模块一样导入即可使用。
    • _main_变量的功能
      • if_main_== “main
      • 表示,只有当程序是直接执行的才会进入
      • if内部,如果是被导入的,则if无法进入
    • 注意事项:不同模块,同名的功能,如果都被导入,那么后导入的会覆盖先导入的
  • 自定义python包

    • 从物理上看,包就是一个文件夹,在该文件夹下包含了一个_init_.py文件,该文件夹可用于包含多个模块文件
    • 从逻辑上看,包的本质依然是模块
    • 创建包步骤如下:
      • 新建包 my_package
      • 新建包内模块: my_modulel和my_module2
      • 模块内代码如下
    • 注意:新建包后,包内部会自动创建_init_.py文件,这个文件控制着包的导入行为
    • 创建包会默认自动创建的文件,通过这个文件来表示一个文件夹是Python的包,而非普通的文件夹。
    • _all_变量的作用:
      • 同模块中学习到的是一个作用,控制 import* 能够导入的内容
  • 第三方包

    • 我们知道,包可以包含一堆的Python模块,而每个模块又内含许多的功能。
    • 所以,我们可以认为:一个包,就是一堆同类型功能的集合体。
    • 在Python程序的生态中,有许多非常多的第三方包(非Python官方),可以极大的帮助我们提高开发效率,如:
      • 科学计算中常用的: numpy包
      • 数据分析中常用的:pandas包
      • 大数据计算中常用的:pyspark、apache-flink包
      • 图形可视化常用的: matplotlib、pyecharts
      • 人工智能常用的: tensorflow
    • 但是由于是第三方,所以Python没有内置,所以我们需要安装它们才可以导入使用。
    • 安装第三方包-pip
      • 第三方包的安装非常简单,我们只需要使用Python内置的pip程序即可。
      • 打开命令提示符程序,在里面输入:pip install 包名称 即可通过网络快速安装第三方包
      • 由于pip是连接的国外的网站进行包的下载,所以有的时候会速度很慢。
      • 我们可以通过如下命令,让其连接国内的网站进行包的安装:
        • pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
        • https://pypi.tuna.tsinghua.edu.cn/simple 是清华大学提供的一个网站,可供pip程序下载第三方包

json

  • json:是一种轻量级的数据交互格式,采用完全独立于编程语言的文本格式来存储和表示数据(就是字符串)
    • Python语言使用JSON有很大优势,因为: JSON无非就是一个单独的字典或一个内部元素都是字典的列表
    • 所以JSON可以直接和Python的字典或列表进行无缝转换。
  • json格式数据转化
    • 通过 json.dumps(data) 方法把python数据转化为了 json数据
      • data = json.dumps(data)
      • 如果有中文可以带上: ensure_ascii=False 参数来确保中文正常转换
    • 通过 json.loads(data) 方法把josn数据转化为了python列表或字典
      • data = json.loads(data)

pyecharts模块

  • 如果想要做出数据可视化效果图,可以借助pyecharts模块来完成

  • 概况:Echarts是个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可,而Python是门富有表达力的语言,很适合用于数据处理.当数据分析遇上数据可视化时pyecharts诞生了.

  • set_global_opts 方法

    • 这里全局配置选项可以通过set_global_opts方法来进行配置,相应的选项和选项的功能如下:
      • TitleOpts:标题配置项
      • LegendOpts:图例配置项
      • ToolboxOpts:工具箱配置项
      • VisualMapOpts:视觉映射配置项
      • TooltipOpts:提示框配置项
      • DataZoomOpts:区域缩放配置项
line.set_global_opts(
    title_opts=Title0pts("测试", pos_left="center", pos_bottom="1%"),
    legend_opts=LegendOpts(is_show=True),
    toolbox_opts=Toolbox0pts(is_show=True),
    visualmap_opts=VisualMapOpts(is_show=True),
    tooltip_opts=Tooltip0pts(is_show=True),
)
  • pyecharts模块中有很多的配置选项,常用到三个类别的选项:
    • 全局配置选项
    • 系列配置选项
  • 全局配置项能做什么?
    • 配置图表的标题
    • 配置图例
    • 配置鼠标移动效果
    • 配置工具栏
    • 等整体配置项
地图演示
  • Timeline() 时间线
# 设置自动播放
timeline.add_schema(
    play_interval=1000,     # 自动播放的时间问隔,单位毫秒
    is_timeline_show=True,  # 是否在自动播放的时候,显示时间线
    is_auto_play=True,      # 是否自动播放
    is_loop_play=True        # 是否循环自动播放
)

对象

  • 构造方法
    • Python类可以使用: __init__()方法,称之为构造方法。
    • 可以实现:
      • 在创建类对象(构造类)的时候,会自动执行
      • 在创建类对象(构造类)的时候,将传入参数自动传递给_init_方法使用
方法功能
__init__构造方法,可用于创建类对象的时候设置初始化行为
__str__用于实现类对象转字符串的行为
__lt__用于2个类对象进行小于或大于比较
__le__用于2个类对象进行小于等于或大于等于比较
__eq__用于2个类对象进行相等比较
  • 封装

    • 封装表示的是,将现实世界事物的:
      • 属性
      • 行为
    • 封装到类中,描述为:
      • 成员变量
      • 成员方法
    • 从而完成程序对现实世界事物的描述
  • 私有成员

    • 既然现实事物有不公开的属性和行为,那么作为现实事物在程序中映射的类,也应该支持。
    • 类中提供了私有成员的形式来支持。
      • 私有成员变量
      • 私有成员方法
    • 定义私有成员的方式非常简单,只需要:
      • 私有成员变量:变量名以_开头(2个下划线)
      • 私有成员方法:方法名以_开头(2个下划线)
    • 即可完成私有成员的设置
  • 继承

    • Python的类之间也支持多继承,即一个类,可以继承多个父类
      class 类名(父类1, 父类2, ..., 父类N):
          类内容
      
  • 变量注解

    # var_1: int = 10
    # var_2: str = "itheima"
    # var_3: bool = True
    # 类对象类型注解
    class Student:
        passstu: Student = Student()
    
    # 基础容器类型注解
    my_list: list = [1, 2, 3]
    # my_tuple: tuple = (1, 2, 3)
    # my_dict: dict = {"itheima": 666}
    
    # 容器类型详细注解
    ny_list: list[int] = [1, 2, 3]
    my_tuple: tuple[int, str, bool] = (1, "itheima", True) 
    my_dict: dict[str, int] = f"itheima": 666}
    
    # 在注释中进行类型注解
    var_1 = random.randint(1, 10)# type: int
    var_2 = json.loads("{"name": "zhangsan"}") # type: dict[str, str)
    def func():
        pass
    var_3 = func() # type: int
    
  • 函数(方法)返回值的类型注解

    • 语法如下:
      def 函数方法名(形参: 类型, ....., 形参: 类型) -> 返回值类型:
          pass
      

SQL

  • 由于数据库管理系统(数据库软件)功能非常多,不仅仅是存储数据,还要包含:数据的管理、表的管理、库的管理、账户管理、权限管理等等。
  • 所以,操作数据库的SQL语言,也基于功能,可以划分为4类:
    • 数据定义: DDL (Data Definition Language)
      • 库的创建删除、表的创建删除等
    • 数据操纵: DML (Data Manipulation Language)
      • 新增数据、删除数据、修改数据等
    • 数据控制: DCL (Data Control Language)
      • 新增用户、删除用户、密码修改、权限管理等
    • 数据查询: DQL (Data Query Language)
      • 基于需求查询和计算数据
  • 查看有哪些表
    • SHOW TABLES; 注意:需要先选择数据库哦
  • 创建表
    • CREATE TABLE 表名称(列名称 列类型,列名称 列类型,…);
    • 列类型有
      • int – 整数
      • float – 浮点数
      • varchar(长度) – 文本,长度为数字,做最大长度
      • date – 日期类型
      • timestamp – 时间戳类型
  • 删除表
    • DROP TABLE 表名称;
    • DROP TABLE IF EXISTS表名称;
  • 更新数据
    • UPDATE 表名 SET 列=值 [WHERE 条件判断];
from pymysql import Connection

# 获取到MySQL数据库的链接对象
conn = Connection(
    host='localhost',   # 主机名(或IP地址)
    port=3306,          # 端口,默认3306
    user='root',        # 账户名
    password='abc-123', # 密码
    autocommit=True     # 自动提交  默认为否
)

# 打印MySQL数据库软件信息
print(conn.get_server_info())

# 获取游标对象
cursor = conn.cursor()
conn.select_db("test")  # 先选择数据库

# 使用游标对象, 执行sql语句
# cursor.execute("CREATE TABLE test_pymysql(id INT, info VARCHAR(255))")
cursor.execute("SELECT * from student")

results = cursor.fetchall()
# print(results)

for r in results:
    print(r)

cursor.execute("INSERT INTO student values(10001, '周', 31)")

# 通过commit确认
# conn.commit()

# 关闭到数据库的链接
conn.close()

PySpark

  • Apache Spark是用于大规模数据(large-scala data) 处理的统一(unified)分析引擎
    • pip install pyspark
    • 数据输入
    • 数据计算
    • 数据输出
    • 分布式集群运行

数据输入

# 导包
from pyspark import SparkConf, SparkContext

# 创建SparkConf类对象
conf = SparkConf().setMaster("local[*]").setAppName("test_spark_app")

# 基于SparkConf类对象创建SparkContext类对象
sc = SparkContext(conf=conf)

# 打印PySpark的运行版本
print(sc.version)

#停止SparkContext对象的运行(停止PySpark程序)
sc.stop()
  • RDD对象

    • PySpark支持多种数据的输入,在输入完成后,都会得到一个: RDD类的对象
    • RDD全称为:弹性分布式数据集(Resilient Distributed Datasets)
    • PySpark针对数据的处理,都是以RDD对象作为载体,即:
      • 数据存储在RDD内
      • 各类数据的计算方法,也都是RDD的成员方法
      • RDD的数据计算方法,返回值依旧是RDD对象
  • Python数据容器转RDD对象

    • PySpark支持通过SparkContext对象的parallelize成员方法,将以下类型转换为PySpark的RDD对象:
      • list
      • tuple
      • set
      • dict
      • str
    • 注意:
      • 字符串会被拆分出1个个的字符,存入RDD对象
      • 字典仅有key会被存入RDD对象
    • .parallelize(数据容器对象)
    from pyspark import SparkConf, SparkContext
    conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
    sc = SparkContext(conf=conf)
    
    # 通过parallelize方法将Python对象加载到Spark内,成为RDD对象
    rdd1 = sc.parallelize([1, 2, 3, 4, 5])
    rdd2 = sc.parallelize((1, 2, 3, 4, 5))
    rdd3 = sc.parallelize({1, 2, 3, 4, 5})
    rdd4 = sc.parallelize("abcdefg")
    rdd5 = sc.parallelize({"key1": "value1", "key2": "value2"})
    
    # 如果要查看RDD里面有什么内容,需要用collect()方法
    print(rdd1.collect())
    print(rdd2.collect())
    print(rdd3.collect())
    print(rdd4.collect())
    print(rdd5.collect())
    
    sc.stop()
    
  • 读取文件转RDD对象PySpark也支持通过SparkContext入口对象,来读取文件,来构建出RDD对象。

    • .textFile(文件路径)
    from pyspark import SparkConf, SparkContext
    conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
    sc = SparkContext(conf=conf)
    
    # 通过textFile方法,读取文件数据加载到Spark内,成为RDD对象
    print(sc.textFile("D:/temp.txt").collect())
    
    sc.stop()
    

数据计算

  • map方法

    • PySpark的数据计算,都是基于RDD对象来进行的,那么如何进行呢?
    • 自然是依赖,RDD对象内置丰富的:成员方法(算子)
  • map算子

    • 功能:map算子,是将RDD的数据一条条处理(处理的逻辑 基于map算子中接收的处理函数 ),返回新的RDD
    • 语法:
      rdd.map(func)
      # func :   f:(T) → U
      # f: 表示这是一个函数(方法)
      # (T)→ U 表示的是方法的定义:
      # ()表示传入参数,(T)表示 传入1个参数,()表示没有传入参数
      # T 是泛型的代称,在这里表示 任意类型
      # U 也是泛型代称,在这里表示 任意类型
      # → U 表示返回值
      # (T) → U 总结起来的意思是: 这是一个方法,这个方法接受一个参数传入,传入参数类型不限. 返回一个返回值,返回值类型不限
      # (A) → A 总结起来的意思是:这是一个方法,这个方法接受一个参数传入,传入参数类型不限。返回一个返回值,返回值和传入参数类型一致
      
      from pyspark import SparkConf, SparkContext
      
      conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
      sc = SparkContext(conf=conf)
      
      # 准备一个RDD
      rdd = sc.parallelize([1, 2, 3, 4, 5])
      
      # 通过map方法将全部数据都乘以10
      # def funcc(data):
      #     return data * 10
      
      # 链式调用
      rdd2 = rdd.map(lambda x: x * 10).map(lambda  x: x + 5)
      
      print(rdd2.collect())
      
  • flatMap

    • 功能: 对rdd执行map操作,然后进行 解除嵌套操作.
    • 解除嵌套:
      • 嵌套的list
        • lst = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
      • 如果解除了嵌套l
        • st = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    from pyspark import SparkConf, SparkContext
    if __name__ == '__main__':
      # 0. 构建Spark执行环境
      conf = SparkConf().setAppName("create rdd").setMaster("local[*]")
      sc= SparkContext(conf=conf)
      
      rdd = sc.parallelize(["a b c", "a c e", "e c a"])
      
      # 按照空格切分数据后,解除嵌套
      print(rdd.flatMap(lambda x: x.split(" ")).collect())
    
  • reduceByKey算子

    • 功能:针对KV型RDD,自动按照key分组,然后根据你提供的聚合逻辑,完成组内数据(value)的聚合操作.
    • 用法:rdd.reduceByKey(func)
      • func: (V, V) → V
      • 接受2个传入参数(类型要一致),返回一个返回值,类型和传入要求一致。
    • reduceBeKey中的聚合逻辑是:
      • 比如,有[1,2,3,4,5],然后聚合函数是:lambda a,b:b
    • 注意:
      • reduceByKey中接收的函数 只负责聚合,不理会分组
      • 分组是自动 by key来分组的.
    rdd = sc.parallelize([('a', 1), ('a', 1), ('b', 1), ('b', 1), ('b', 1)])
    result = rdd.reduceByKey(lambda a, b: a + b)
    print(result.collect())
    
    #结果:
    [('b', 3), ('a', 2)]
    
  • Filter

    • 功能:过滤想要的数据进行保留
    • 语法:
      • rdd.filter(func)
      • func: (T) → bool传入1个参数进来随意类型,返回值必须是True or False
      • 返回是True的数据被保留,False的数据被丢弃
    from pyspark import SparkConf, SparkContext
    if __name__ == '__main__':
        # 0. 构建Spark执行环境
        conf = SparkConf().setAppName("create rdd"). IsetMaster("local[*]")
        sc= SparkContext(conf=conf)
        rdd = sc.parallelize([1, 2, 3, 4, 5])
        # 保留奇数
        # rdd.filter(lambda x: True if (x % 2 = 1) else False)
        print(rdd.filter(lambda x: x % 2 = 1).collect())
    
  • distinct算子

    • 功能:对RDD数据进行去重,返回新RDD
    • 语法:rdd.distinct() 无需传参
    from pyspark import SparkConf, SparkContext
    if __name__ == '__main__':
        # 0. 构建Spark执行环境
        SparkConf().setAppName("create rdd").setMaster("local[*]")
        sc = SparkContext(conf=conf)
        rdd = sc.parallelize([1, 1, 3, 3, 5, 5, 6, 6, 9, 9])
        # 按照空格切分数据后,解除嵌套
        print(rdd.distinct().collect())
    
  • sortBy

    • 功能:对RDD数据进行排序,基于你指定的排序依据.
    • 语法:rdd.sortBy(func, ascending=False, numPartitions=1)
      • func: (T) → U: 告知按照rdd中的哪个数据进行排序,比如lambda x: x[1]表示按照rdd中的第二列元素进行排
      • ascending True 升序 False 降序
      • numPartitions: 用多少分区排序
数据输出
  • collect算子
    • 功能:将RDD各个分区内的数据,统一收集到Driver中,形成一个List对象
    • 用法:rdd.collect()
      • 返回值是一个list
  • reduce算子
    • 对RDD进行两两聚合
  • take算子
    • 取出RDD前N个元素,组成list返回
  • count算子
    • 计算RDD有多少条数据,返回值是一个数字
# 准备RDD
rdd = sc.parallelize([1, 2, 3, 4, 5])

# collect算子,输出RDD为list对象
rdd_list: list = rdd.collect() 
print (rdd_list)
print (type (rdd_list))

# reduce算子,对RDD进行两两聚合
num = rdd.reduce(lambda a, b: a + b)
print (num)

# take算子,取出RDD前N个元素,组成List返回
take_list = rdd.take(3) 
print (take_list)

# count,统计rdd内有多少条数据,返回值为数字
  • saveAsTextFile算子
    • 功能: 将RDD的数据写入文本文件中
    • 支持 本地写出, hdfs等文件系统.
    • 注意事项:
      • 调用保存文件的算子,需要配置Hadoop依赖
        • 下载Hadoop安装包
          • http://archive.apache.org/dist/hadoop/common/hadoop-3.0.0/hadoop-3.0.0.tar.gz
        • 解压到电脑任意位置
        • 在Python代码中使用os模块配置: os.environ[‘HADOOP_HOME’] = ‘HADOOP解压文件夹路径’
        • 下载winutils.exe,并放入Hadoop解压文件夹的bin目录内
          • https://raw.githubusercontent.com/steveloughran/winutils/master/hadoop-3.0.0/bin/winutils.exe
        • 下载hadoop.dll,并放入:C:/Windows/System32文件夹内
          • https://raw.githubusercontent.com/steveloughran/winutils/master/hadoop-3.0.0/bin/hadoop.dll
    • 修改rdd分区为1个
      • 方式1, SparkConf对象设置属性全局并行度为1:
        conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
        conf.set("spark.default.parallelism", "1")
        sc = SparkContext(conf=conf)
        
      • 方式2,创建RDD的时候设置(parallelize方法传入numSlices参数为1)
        rdd1 = sc.parallelize([1, 2, 3, 4, 5], numSlices=1)
        rdd1 = sc.parallelize([1, 2, 3, 4, 5], 1)
        

  • 闭包

    • 定义:
      • 双层嵌套函数,内层函数可以访问外层函数的变量
      • 将内存函数作为外层函数的返回,此内层函数就是闭包函数
    • 优缺点:
      • 优点:不定义全局变量,也可以让函数持续访问和修改一个外部变量
      • 优点:闭包函数引用的外部变量,是外层函数的内部变量。作用域封闭难以被误操作修改
      • 缺点:额外的内存占用
    • nonlocal关键字的作用
      • 在闭包函数(内部函数中)想要修改外部函数的变量值
      • 需要用nonlocal声明这个外部变量
  • 装饰器

    • 装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
      def outer(func):
          def innen():
              print("我要睡觉了")
              func()
              print("我起床了")
          return inner
      
      @outer
      def sleep():
          import random
          import time
          print("睡眠中......")
          time.sleep(random.randint(1, 5))
      
      sleep()
      
  • 设计模式

    • 设计模式是一种编程套路,可以极大的方便程序的开发。
    • 最常见、最经典的设计模式,就是我们所学习的面向对象了。
    • 除了面向对象外,在编程中也有很多既定的套路可以方便开发,我们称之为设计模式:
    • 单例、工厂模式建造者、责任链、状态、备忘录、解释器、访问者、观察者、中介、模板、代理模式等等模式
    • 单例模式
      • 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。
      • 在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
      • 定义:保证一个类只有一个实例,并提供一个访问它的全局访问点
      • 适用场景:当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时。
    • 工厂模式
      • 当需要大量创建一个类的实例的时候,可以使用工厂模式。
      • 即,从原生的使用类的构造去创建对象的形式迁移到,基于工厂提供的方法去创建对象的形式。
      • 优点:
        • 大批量创建对象的时候有统一的入口,易于代码维护
        • 当发生修改,仅修改工厂类的创建方法即可符
        • 合现实世界的模式,即由工厂来制作产品(对象)
      class Person:
          pass
      
      class Worker(Person): 
          pass
      
      class Student(Person):
          pass
      
      class Teacher(Person): 
          pass 
      
      class PersonFactory: 
          def get_person(self, p_type): 
              if p_type == 'w': 
                  return Worker() 
              elif p_type == 's': 
                  return Student() 
              else: 
                  return Teacher()
                  
      pf = PersonFactory()
      worker = pf.get_person('w') 
      stu = pf.get_person('s') 
      teacher = pf.get_person('t')
      
  • 多线程

    • 现代操作系统比如Mac OS x, UNIX, Linux, Windows等,都是支持“多任务"的操作系统。
    • 进程:就是一个程序,运行在系统之上,那么便称之这个程序为一个运行进程,并分配进程ID方便系统管理。
      • 进程就好比一家公司,是操作系统对程序进行运行管理的单位
      • 操作系统中可以运行多个进程,即多任务运行
    • 线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位。
      • 线程就好比公司的员工,进程可以有多个线程(员工),是进程实际的工作者
      • 一个进程内可以运行多个线程,即多线程运行
    • 注意点:
      • 进程之间是内存隔离的,即不同的进程拥有各自的内存空间。这就类似于不同的公司拥有不同的办公场所。
      • 线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间的。这就好比,公司员工之间是共享公司的办公场所。
    • 并行执行
      • 并行执行的意思指的是同一时间做不同的工作。
      • 进程之间就是并行执行的,操作系统可以同时运行好多程序,这些程序都是在并行执行。
      • 除了进程外,线程其实也是可以并行执行的。
      • 也就是比如一个Python程序,其实是完全可以做到:
        • 一个线程在输出:你好
        • 一个线程在输出:Hello
      • 像这样一个程序在同一时间做两件乃至多件不同的事情,我们就称之为:多线程并行执行
    • threading模块
      • 绝大多数编程语言,都允许多线程编程, Pyhton也不例外。
      • Python的多线程可以通过threading模块来实现。
      import threading
      
      thread_obj = threading.Thread([group [, target [, name [, args [, kwargs]]]]])
      # group:暂时无用,未来功能的预留参数
      # target: 执行的目标任务名
      # args:以元组的方式给执行任务传参
      # kwargs:以字典方式给执行任务传参
      # name:线程名,一般不用设置
      
      # 启动线程,让线程开始工作
      thread_obj.start()
      
      import time 
      import threading
      
      def sing(msg):
          while True:
              print(msg)
              time.sleep(1)
              
      def dance(msg):
          while True:
              print(msg)
              time.sleep(1)
              
      if __name__ == '__main__':
          # 创建一个唱歌的线程
          sing_thread = threading.Thread(target=sing, args=("我在唱歌,啦啦啦...", ))
          # 创建一个跳舞的线程
          dance_thread = threading.Thread(target=dance, hkwargs={"msg": "我在跳舞,呱呱呱..."})
          # 让线程去干活吧
          sing_thread.start()
          dance_thread.start()
      
  • socket

    • socket (简称套接字)是进程之间通信一个工具,好比现实生活中的插座,所有的家用电器要想工作都是基于插座进行,进程之间想要进行网络通信需要socket。
    • Socket负责进程之间的网络数据传输,好比数据的搬运工。
    • 2个进程之间通过Socket进行相互通讯,就必须有服务端和客户端
      • Socket服务端: 等待其它进程的连接、可接受发来的消息、可以回复消息
      • Socket客户端:主动连接服务端、可以发送消息、可以接收回复
Socket服务端

Socket服务端编程主要分为如下几个步骤:

  1. 创建socket对象
    import socket 
    socket_server = socket.socket()
    
  2. 绑定socket_server到指定IP和地址
    socket_server.bind(host, port)
    
  3. 服务端开始监听端口
    socker_server.listen(backlog) 
    # backlog为int整数,表示允许的连接数量,超出的会等待,可以不填,不填会自动设置一个合理值
    
  4. 接收客户端连接,获得连接对象
    conn, address = socket_server.accept()
    print(f"接收到客户端连接,连接来自: {address}")
    # accept方法是阻塞方法,如果没有连接,会卡再当前这一行不向下执行代码
    # accept返回的是一个二元元组,可以使用上述形式,用两个变量接收二元元组的2个元素
    
  5. 客户端连接后,通过recv方法,接收客户端发送的消息
    while True:
        data = conn.recv(1024).decode("UTF-8")
        # recv方法的返回值是字节数组(Bytes) ,可以通过decode使用UTF-8解码为字符串
        # recv方法的传参是buffsize,缓冲区大小,一般设置为1024即可
        if data == 'exit':
            break
        print("接收到发送来的数据: ", data)
        # 可以通过while True无限循环来持续和客户端进行数据交互
        #可以通过判定客户端发来的特殊标记,如exit,来退出无限循环
    
  6. 通过conn (客户端当次连接对象),调用send方法可以回复消息
    while True:
        data = conn.recv(1024).decode("UTF-8") 
        if data == 'exit':
            break
        print("接收到发送来的数据: ", data)
        
        conn send"你好呀哈哈哈".encode("UTF-8")
    
  7. conn (客户端当次连接对象)和socket-server对象调用close方法,关闭连接
# 演示Socket服务端开发

import socket
# 创建Socket对象
socket_server = socket.socket()
# 绑定ip地址和端口
socket_server.bind(("localhost", 8888))
# 监听端口
socket_server.listen(1)
# listen方法内接受一个整数传参数,表示接受的链接数量
# 等待客户端链接
# result: tuple = socket_server.accept()
# conn = result[0]      # 客户端和服务端的链接对象
# address = result[1]   # 客户端的地址信息
conn, address = socket_server.accept()
# accept方法返回的是二元元组(链接对象, 客户端地址信息)
# 可以通过 变量1, 变量2 = socket_server.accept()的形式,直接接受二元元组内的两个元素
# accept()方法,是阻塞的方法,等待客户端的链接,如果没有链接,就卡在这一行不向下执行了

print(f"接收到了客户端的链接,客户端的信息是: {address}")

while True:
    # 接受客户端信息,要使用客户端和服务端的本次链接对象,而非socket_server对象
    data: str = conn.recv(1024).decode("UTF-8")
    # recv接受的参数是缓冲区大小,一般给1024即可
    # recv方法的返回值是一个字节数组也就是bytes对象,不是字符串,可以通过decode 方法通过UTF-8编码,将字节数组转换为字符串对象
    print(f"客户端发来的消息是:{data}")
    # 发送回复消息msg = input("请输入你要和客户端回复的消息:")
    if msg == 'exit':
        break
    conn.send(msg.encode("UTF-8"))

# 关闭链接
conn.close()
socket_server.close()
Socket客户端

Socket客户端编程主要分为如下几个步骤:

  1. 创建socket对象
    import socket 
    socket_client = socket.socket()
    
  2. 连接到服务端
    socket_client.connect(("localhost", 8888))
    
  3. 发送消息
    while True: # 可以通过无限循环来确保持续的发送消息给服务端
        send_msg = input("请输入要发送的消息")
        if send_msg = 'exit':
            #通过特殊标记来确保可以退出无限循环
            break
        socket_client.send(send_msg.encode("UTF-8"))    #消息需要编码为字节数组(UTF-8编码)
    
  4. 接收返回消息
    while True:
        send_msg = input("请输入要发送的消息").encode("UTF-8")
        socket_client.send(send_msg)
        recv_data = socket_client.recv(1024)    # 1024是缓冲区大小,一般1024即可
        # recv方法是阻塞式的,即不接收到返回,就卡在这里等待
        print("服务端回复消息为:",recv_data.decode("UTF-8"))   # 接受的消息需要通过UTF-8解码为字符串
    
  5. 关闭链接
    socket_client.close()    # 最后通过close关闭链接
    
# 演示Socket客户端开发

import socket
# 创建socket对象
socket_client = socket.socket()
# 连接到服务端
socket_client.connect(("localhost", 8888))

while True:
    # 发送消息
    msg = input("请输入要给服务端发送的消息: ")
    if msg == 'exit':
        break
    socket_client.send(msg.encode("UTF-8"))
    # 接收返回消息
    recv_data = socket_client.recv(1024)    # 1024是缓冲区的大小,一般1024即可。 同样recv方法是阻塞的
    print(f"服务端回复的消息是: {frecv_data.decode('UTF-8')}")
    
# 关闭链接
socket_client.close()

正则表达式

  • 正则表达式正则表达式,又称规则表达式(Regular Expression),是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式(规则)的文本。

    • 简单来说,正则表达式就是使用:字符串定义规则,并通过规则去验证字符串是否匹配。
      • 比如,验证一个字符串是否是符合条件的电子邮箱地址,只需要配置好正则规则,即可远配任意邮箱。
      • 比如通过正则规则: (^[\w-]+(.[\w-]+)*@[\w-]+(.[\w-]+)+$)即可匹配一个字符串是否是标准邮箱格式
      • 但如果不使用正则,使用if else来对字符串做判断就非常困难了。
  • Python正则表达式,使用re模块,并基于re模块中三个基础方法来做正则匹配。

  • 分别是: match,search、findall三个基础方法

    • re.match(匹配规则,被匹配字符串)

      • 从被匹配字符串开头进行匹配,匹配成功返回匹配对象(包含匹配的信息)
        s = 'python itheima python itheima python itheima' 
        result = re.match('python', s)
        print(result) # <re.Match object; span=(0, 6), match='python'> 
        print (result. span()) # (0, 6)
        print(result.group()) # python
        
      • 匹配不成功返回空
        s = '1python itheima python itheima python itheima'   
        result = re.match('python', s) 
        print(result) # None
        
    • search(匹配规则,被匹配字符串)

      • 搜索整个字符串,找出匹配的。从前向后,找到第一个后,就停止,不会继续向后
        s = '1python666itheima666python666'   
        result = re.search('python', s)
        print(result) # <re.Match object; span=(1, 7), match='python'> 
        print (result. span()) # (1, 7)
        print(result.group()) # python
        
      • 整个字符串都找不到,返回None
        s = 'itheima666'    
        result = re.search('python', s) 
        print(result) # None
        
    • findall(匹配规则,被匹配字符串)

      • 匹配整个字符串,找出全部匹配项
        s = '1python666itheima666python666'   
        result = re.findall('python', s)
        print(result) # ['python', 'python']
        
      • 找不到返回空list: []
        s = '1python666itheima666python666'    
        result = re.search('itcast', s) 
        print(result) # []
        
  • 元字符匹配

    • 单字符匹配
      字符功能
      .匹配任意1个字符(除了\n)1. 匹配点本身
      []匹配[]中列举的字符
      \d匹配数字,即0-9
      \D匹配非数字
      \s匹配空白,即空格、tab键
      \S匹配非空白
      \w匹配单词字符,即a-z、A-Z、0-9、_
      \W匹配非单词字符
    • 示例:
      # 字符串 
      s = "itheima1 @@python2 !!666 ##itcast3"
      # 找出全部数字: 
      re.findall(r'\d',s)
      # 字符串的r标记,表示当前字符串是原始字符串,即内部的转义字符无效而是普通字符
      # 找出特殊字符:
      re.findall(r'\W',s)
      # 找出全部英文字母:
      re.findall(r'[a-zA-Z]', s)
      # []内可以写: [a-zA-Z0-9]这三种范围组合或指定单个字符如[aceDFG135]
      
    • 数量匹配
      字符功能
      *匹配前一个规则的字符出现0至无数次
      +匹配前一个规则的字符出现1至无数次
      ?匹配前一个规则的字符出现0次或1次
      {m}匹配前一个规则的字符出现m次
      {m,}匹配前一个规则的字符出现最少m次
      {m,n}匹配前一个规则的字符出现m到n次
    • 边界匹配
      字符功能
      ^匹配字符串开头
      $匹配字符串结尾
      \b匹配一个单词的边界
      \B匹配非单词边界
    • 分组匹配
      字符功能
      |匹配左右任意一个表达式
      ()将括号中字符作为一个分组
    # 匹配账号,只能由字母和数字组成,长度限制6到10位
    r = '^[0-9a-zA-Z]{6, 10}$'
    s = '1234567'
    print(re.findall(r, s))
    # 匹配QQ号,要求纯数字,长度5-11,第一位不为0
    r = '[1-9][0-9]{4,10}'
    s = '012345678'
    print(re.findall(r, s))
    # 匹配邮箱地址,只允许qq、163、gmail这三种邮箱地址
    # abc.efg.daw@qq.com.cn.eu.qq.aa.cc
    # abc@qq.com
    # {内容},{内容},{内容},{内容},{内容},{内容},{内容},{内容}@{内容},{内容},{内容}
    r = r'(^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+$)'
    #  s = 'a.b.c.d.e.f.g@qq.com.a.z.c.d.e'
    s = 'a.b.c.d.e.f.g@126.com.a.z.c.d.e'
    
    print(re.match(r, s))
    

递归

import os
def test_os():
    """演示os模块的3个基础方法"""
    print(os.listdir("D:/test"))        # 列出路径下的内容
    print(os.path.isdir("D:/test/a"))   # 判断指定路径是不是文件夹
    print (os.path.exists("D:/test"))   # 判断指定路径是否存在

def get_files_recursion_from_dir(path):
    """
    从指定的文件夹中使用递归的方式,获取全部的文件列表
    :param path: 被判断的文件夹
    :return: list,包含全部的文件,如果目录不存在或者无文件就返回一个空list
    """
    print(f"当前判断的文件夹是: {path}")
    file_list = []
    if os.path.exists(path):
        for f in os.listdir(path):
            new_path = path + "/" + f
            if os.path.isdir(new_path):
                # 进入到这里,表明这个目录是文件夹不是文件
                file_list += get_files_recursion_from_dir(new_path)
            else:
                file_list.append(new_path)
    else:
        print(f"指定的目录{path},不存在")
        return []
    return file_list 
    
if __name__=='__main__':
    print(get_files_recursion_from_dir("D:/test"))
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值