1.掌握字面量的含义
代码中,被写在代码中固定的值
2.常见的字面量类型
整数、浮点数、字符串
3.如何基于print语句完成各类字面量的输出
注释的作用:代码中的解释性语句,用来对代码内容进行注释,注释不是代码,不会被程序执行
注释的分类
单行注释:以#开头,#右边 的所有文字当作说明,而不是真正要执行的程序,起辅助说明作用
建议在#和注释内容之间,间隔一个空格
单行注释一般用于对一行或一小部分代码进行解释
多行注释:以一对三个双引号引起来("""注释内容""")来解释说明一段代码的作用使用方法
变量:在程序运行时,能储存计算结果或能表示值的抽象概念,简单的说,变量就是在程序运行时,记录数据用的
变量的定义格式:
变量名称=变量的值
变量的特征:变量的值可以发生改变
print语句如何输出多份内容
print(内容1,内容2,......内容n)
python中如何做减法
使用符号-即可完成减法运算
类型 | 描述 | 说明 |
string | 字符串类型 | 用引号引起来的数据都是字符串 |
int | 整型(有符号) | 数字类型,存放整数 如 -1,10,0等 |
float | 浮点数(有符号) | 数字类型,存放小数 |
type()语句
变量有类型吗
我们通过type(变量)可以输出类型,这是查看变量的类型还是数据的类型
查看的是:变量存储的数据的类型。因为,变量无类型,但是它存储的数据有
数据类型的转换,将会是我们以后经常使用的功能,如:
从文件中读取的数字,默认是字符串,我们需要转换成数字类型
后续学习的input语句,默认结果是字符串,若需要数字也需要转换
将数字转换成字符串用以写出到外部系统
语句(函数) | 说明 |
int(x) | 将x转换成一个整数 |
float(x) | 将x转换成一个浮点数 |
str(x) | 将对象x转换成字符串 |
任何类型都可以转换成字符串,对不对?
正确
字符串可以随意转换成数字,对不对?
错误,字符串内必须只有数字才可以
浮点数转换成整数会丢失精度
什么是标识符
在python中,我们可以给很多东西起名字
变量的名字
方法的名字
类的名字,等等
这些名字,我们统一称为标识符,用来做内容的标识
标识符:用来给变量、类、方法等命名
标识符命名规则-内容限定
标识符命名中,只允许出现
- 英文
- 中文
- 数字
- 下划线
这四类元素
1.不推荐使用中文
2.数字不可以开头
标识符命名规则-大小写敏感
标识符命名规则-不可使用关键字
python中有一系列单词,称之为关键字,有特定用途,不可以使用它们作为标识符
变量命名规范
- 变量名
- 类名
- 方法名
不同的标识符,有不同的规范
变量的命名规范-见名知意
变量命名规范-下划线命名法
多个单词组合变量名,要使用下划线做分隔
first_number
student_nickname
变量命名规范-英文字母全小写
命名变量中的英文字母,应全部小写
运算符
运算符 | 描述 | 实例 |
+ | ||
- | ||
* | ||
/ | 除 | |
// | 取整数 | |
% | 取余 | |
** | 取指 |
复合赋值运算符
运算符 | 描述 | 实例 |
+= | ||
-= | ||
*= | ||
/= | ||
%= | ||
**= | ||
//= |
字符串的三种定义方式
1.单引号定义法
2.双引号定义法
3.三引号定义法(支持换行操作,使用变量接收它,它就是字符串,不使用变量接收它,就可以作为多行注释使用
字符串的引号嵌套
单引号定义法,可以内含双引号
双引号定义法,可以内含单引号
可以使用转移字符(\)来将引号解除效用,变成普通字符串
字符串拼接
print("学IT来黑马"+”月薪过万")
字符串格式化
1.变量过多,拼接起来实在是太麻烦了
2.字符串无法和数字或者其他类型完成拼接
其中的%s:
%表示:我要占位
s表示:将变量变成字符串放入占位的地方
综合起来的意思是:我先占个位置,等一会有个变量过来,我把它变成字符串放到占位的位置
多个变量占位
变量要用括号括起来
并按照占位的顺序填入
python中,支持非常多的数据类型占位
最常用的是如下三类
格式符号 | 转化 |
%s | 将内容转换成字符串,放入占位位置 |
%d | 将内容转换成整数,放入占位位置 |
%f | 将内容转换成浮点数,放入占位位置 |
1.掌握格式化字符串的过程中做数字的精度控制
字符串格式化-数字精度控制
我们可以使用辅助符号“m.n"来控制数据的宽度和精度
m,控制宽度,要求是数字(很少使用),设置的宽度小于数字自身,不生效
.n,控制小数点精度,要求是数字,会进行小数的四舍五入
示例:
%5d:表示将整数的宽度控制在5位,如数字11,被设置为5d,就会变成: 11,用3个空格补足宽度
%5.2f:表示将宽度控制为5,将小数点精度设置为2
小数点和小数部分也算入宽度计算。如,对11.345设置了%7.2f后,结果是: 11.35。两个空格补足宽度,小数部分限制2位精度后,四舍五入为.35
%.2f:表示不限制宽度,只设置小数点精度为2,如11.345设置%.2f后,结果是11.35
字符串格式化-快速写法
目前通过%符号占位已经很方便了,还能进行精度控制
通过语法:f"内容{变量}"的格式来快速格式化
这种方式:
- 不理会类型
- 不做精度控制
适合对精度没有要求的适合快速使用
对表达式进行格式化
表达式:一条具有明确执行结果的代码语句
在无需使用变量进行数据存储的时候,可以直接格式化表达式,简化代码哦
获取键盘输入
试想一下,我们经常遇到过程序需要我们输入信息的场景
比如:银行取钱
数据输出:print
数据输入:input
input()语句的功能是,获取键盘输入的数据
可以使用input(提示信息)
要注意,无论键盘输入什么类型的数据,获取到的数据永远是字符串类型
布尔类型的定义
布尔类型的字面量:
True表示真(是、肯定)
False表示假(否、否定)
定义变量存储布尔类型数据:
变量名称 = 布尔类型字面量
布尔类型不仅可以自行定义 同时也可以通过计算的来
也就是使用比较运算符进行比较运算得到布尔类型的结果
if语句的基本格式
if 要判断的条件:
条件成立时,要做的事
if else语句
if 条件:
事情1
事情2
事情3
else:
不满足条件时要做的事情1
if else语句:
if 条件1:
条件1满足应该做的事
elif 条件2:
条件2满足应该做的事
else:
所有条件都不满足应该做的事
判断语句的嵌套
许多逻辑的判断,是嵌套的,多层次的
对于这种需求,我们可以:自由组合 if elif else,完成特定需求的要求
循环语句的嵌套,要注意空格缩进
基于空格的缩进来决定层次关系
注意条件的设置,避免出现无限循环
print输出不换行
print("Hello",end=' ')
同while循环不同,for循环是无法定义循环条件的
只能从被处理的数据集中,依次取出内容进行处理
所以,理论上讲,python的for循环无法构建无限循环(被处理的数据集不可能无限大)
range语句
for 临时变量 in 待处理数据集
循环满足条件时执行的代码
待处理数据集,严格来说,称之为:序列类型
序列类型指:其内容可以一个个依次取出的一种类型,包括:
- 字符串
- 列表
- 元组
- 等
语法1:
range(num)
获取一个从0开始,到num结束的数字序列(不含num本身)
如range(5)取得的数据是:[0,1,2,3,4]
语法2:
range(num1,num2)
获得一个从num1开始,到num2结束的数字序列(不含num2本身)
如,range(5,10)取得的数据是:[5,6,7,8,9]
语法3:
range(num1,num2,step)
获得一个从num1开始,到num2结束的数字序列(不含num2本身)
数字之间的步长,以step为准(step默认为1)
如,range(5,10,2)取得的数据是:[5,7,9]
for循环的变量作用域
临时变量,在编程规范上,作用范围是作用域,只限定在for循环内部
如果在for循环外部访问临时变量
- 实际上是可以访问到的
- 在编程规范上是不允许、不建议这么做的
for循环中的临时变量,其作用域限定为:
循环内
这种限定:
是编程规范的限定,而非强制限定
不遵守也能正常运行,但是不建议这么做
如需访问临时变量,可以预先在循环外定义它
continue和break
用以对循环进行临时跳过和直接结束
continue
continue关键字用于:中断本次循环,直接进入下一次循环
continue可以用于:for循环和while循环,效果一致
continue在嵌套循环中的应用
break关键字同样只可以控制:它所在的循环结束
函数
函数:是组织好的,可重复使用的,用来实现特定功能的代码段
函数的定义
def 函数名(传入参数):
函数体
return 返回值
函数使用步骤:
先定义函数
后调用函数
注意事项:参数不需要,可以省略 返回值不需要,可以省略
函数的传入参数
传入参数的功能是:在函数进行计算的时候,接受外部调用时提供的数据
传入参数的作用:
在函数运行的时候,接受外部传入的数据
返回值的语法
def 函数(参数...):
函数体
return 返回值
变量 = 函数(参数)
函数体在遇到return后就结束了,所以写在return后的代码不会执行
None类型
None表示:空的、无实际意义的意思
None作为一个特殊的字面量,用于表示:空、无意义,其有非常多的应用场景
用在if判断上
在if判断中,none等同于false
一般用于在函数中主动返回none,配合if判断做相关处理
函数的说明文档
局部变量
变量作用域指的是变量的作用范围(变量在哪里可用,在哪里不可用)
主要分为两类:局部变量和全局变量
所谓局部变量:定义在函数体内部的变量,只在函数内部生效
global关键字
使用global关键字 可以在函数内部声明
字典的常用操作
字典的特点:可以容纳多个数据,可以容纳不同类型的数据,每一份数据是keyvalue键值对,可以通过key获取到value,key不可重复,不支持下标索引,可以修改,支持for循环,不支持while循环
数据容器可以从以下视角进行简单分类:
是否支持下标索引
支持:列表、元组、字符串-序列类型
不支持:集合、字典-非序列类型
是否支持重复元素:
支持:列表、元组、字符串-序列类型
不支持:集合、字典-非序列类型
是否可以修改
支持-列表、集合、字典
不支持:元组、字符串
列表:一批数据,可修改、可重复的场景
元组:一批数据,不可修改、可重复的储存场景
字符串:一串字符串的存储场景
集合:一批数据,去重存储场景
字典:一批数据,可用key检索value1的存储场景
在遍历上
5类数据容器都支持for循环
列表、元组、字符串支持while循环、集合、字典不支持(无法下标索引)
尽管遍历的形式各有不同,但是,它们都支持遍历操作
数据容器的通用统计功能
len(容器)
统计容器的元素个数
max(容器)
统计容器的最大元素
min(容器)
统计容器的最小元素
容器的通用转换功能
list(容器)
将给定容器转换成列表
str(容器)
将给定容器转换成字符串
tuple(容器)
将给定容器转换成元组
set(容器)
将给定容器转换成集合
多个返回值
如果一个函数要有多个返回值,该如何书写代码
def test_return():
return 1,2
x,y = test_return()
print(x)
print(y)
函数参数种类
使用方式上的不同,函数有4种常见参数使用方式:
位置参数
关键字参数:函数调用时通过“键=值”的形式传递参数
函数调用时,如果有位置参数时,位置参数必须在关键字参数前面,但关键字参数之间不存在先后顺序
缺省参数:默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
作用:当调用函数时没有传递参数,就会使用默认是用缺省参数对应的值
不定长参数
不定长参数:不定长参数也叫可变参数,用于不确定调用的时候会传递多少个参数(不传参也可以)的场景
作用:当调用参数时不确定参数个数时,可以使用不定长参数
不定长参数的类型:
位置传递
关键字传递
位置传递
def user_info(*args):
print(args)
#('TOM',)
user_info('TOM')
#('TOM',18)
user_info('TOM',18)
注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递
关键字传递
def user_info(**kwargs):
print(kwargs)
# {'name':'TOM','age':18,'id':110}
user_info(name='TOM',age=18,id=110)
注意:参数是“键=值”形式的情况下,所有的“键=值”都会被kwargs接收,同时会根据“键=值”组成字典
函数作为参数传递
函数都是接受数据作为参数传入:
数字
字符串
字典、列表、元组等
函数作为参数传递
如下代码:
def test_func(compute):
result = compute(1,2)
print(result)
def compute(x,y):
return x+y
test_func(compute)
计算逻辑的传递而非数据的传递、
就像上述代码那样,不仅仅是相加、相减、相除、等任何逻辑都可以自行定义并作为函数传入
函数本身是可以作为参数,传入另一个函数中进行使用的
将函数传入的作用在于:传入计算逻辑,而非传入数据
函数的定义中
def关键字,可以定义带有名称的函数
lambda关键字,可以定义匿名函数(无名称)
有名称的函数,可以基于名称重复使用
无名称的匿名函数,只可临时使用一次
匿名函数定义语法:
lambda 传入参数:函数体(一行代码)
lambda是关键字,表示定义匿名函数
传入参数表示匿名函数的形式参数,如:x,y表示接收2个形式参数
函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行
文件编码
计算机只能识别:0和1,那么我们丰富的文本文件是如何被计算机识别,并存储在硬盘中的呢
答案:使用编码技术(密码本)将内容翻译成0和1存入
编码技术:翻译的规则,记录了如何将内容翻译成二进制,以及如何将二进制翻译回可识别内容
计算机中有许多可用编码:
UTF-8
GBK
Big5
等
编码有许多,要使用正确的编码,才能对文件进行正确的读写操作
UTF-8是目前全球通用的编码格式
除非有特殊需求,否则,一律以UTF-8格式进行文件编码即可
什么是文件
一篇文章、一段视频、一个可执行程序,都可以被保存为一个文件,并赋予一个文件名。操作系统以文件为单位管理磁盘中的数据。一般来说,文件可分为文本文件、视频文件、音频文件、图像文件、可执行文件等多种类别
文件操作包含哪些内容
文件操作主要包括打开、关闭、读、写等操作
打开文件
读写文件
关闭文件
open()打开函数
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下:
open(name,mode,encoding)
name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)
mode:设置打开文件的模式(访问模式):只读、写入、追加等
encoding:编码格式(推荐使用utf-8)
示例代码:
f = open('python.txt','r'encoding=UTF-8)
#encoding的顺序不是第三位,所以不能用位置参数,用关键字参数直接指定
注意事项:此时的f是open函数的文件对象,对象是python中一种特殊的数据类型,拥有属性和方法,可以使用对象.属性或对象.方法对其进行访问
mode常用的三种基础访问模式
r:以只读方式打开文件,文件的指针将会放在文件的开头,这是默认模式
w:打开一个文件只用于写入,如果该文件已存在则打开文件,并从开头开始编辑,原有内容会被删除,如果该文件不存在,创建新文件
a:打开一个文件用于追加。如果该文件已经存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入
读操作相关方法
read()方法:
文件对象.read(num)
num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据
readlines()方法:
readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
readline()方法:一次读取一行内容
f=open('python.txt')
content = f.readline()
print(f'第一行:{content}')
content = f.readline()
print(f'第二行:{content}')
# 关闭文件
f.close()
# 读取文件 - readline()
line1 = f.readline()
line2 = f.readline()
line3 = f.readline()
读操作相关方法
for循环读取文件行
for line in open("python.txt","r"):
print(line)
# 每一个line临时变量,就记录了文件的一行数据
写操作快速入门
案例演示:
# 1.打开文件
f = open('python.txt','w')
#2.文件写入
f.write('hello world')
#3.内容刷新
f.flush()
注意:
直接调用write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区
当调用flush的时候,内容会真正写入文件
1.写入文件使用open函数的"w"模式进行写入
2.写入的方法有:
write(),写入内容
flush(),刷新内容到硬盘
3.注意事项
w模式,文件不存在,会创建新文件
w模式,文件存在,会清空原有内容
close()方法,带有flush()方法的功能
文件的追加
追加写入操作快速入门
案例演示:
# 1.打开文件,通过a模式打开即可
f = open('python.txt','a')
# 2.文件写入
f.write('hello world')
# 3.内容刷新
f.flush()
注意:
a模式,文件不存在会创建文件
a模式,文件存在会在最后,追加写入文件
什么是异常
当检测到一个错误时,python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的异常,也就是我们常说的bug
什么是异常:异常就是程序运行的过程中出现了错误
bug是什么意思:bug就是指异常的意思
异常的捕获
为什么需要捕获异常
整个程序因为一个bug停止运行
对bug进行提醒,整个程序继续运行
捕获异常的作用在于:提前假设某处会出现异常,做好提前准备,当真的出现异常的时候,可以有后续手段
基本语法:
try:
可能发生错误的代码
except:
如果出现异常执行的代码
快速入门
需求:尝试以“r“模式打开文件,如果文件不存在,则以”w“方式打开
try:
f = open('linux.txt','r')
except:
f = open('linux.txt','w')
捕获指定异常
基本语法:
try:
print(name)
except NameError as e:
print('name变量名称未定义错误')
注意事项
1.如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常
2.一般try下方只放一行尝试执行的代码
捕获多个异常
当捕获多个异常时,可以把要捕获的异常类型的名字,放到except后,并使用元组的方式进行书写
异常else
else表示的是如果没有异常要执行的代码
try:
print(1)
except Exception as e:
print(e)
else:
print('我是else,是没有异常的时候执行的代码')
异常的finally
finally表示的是无论是否异常都要执行的代码,例如关闭文件
异常具有传递性
python模块,是一个python文件,以.py结尾。模块能定义函数,类和变量,模块里也能包含可执行的代码
模块的作用:python中有很多各种不同的模块,每一个模块都可以帮助我们快速的实现一些功能
大白话:模块就是一个python文件,里面有类、函数、变量等,我们可以拿过来用(导入模块去使用)
模块的导入方式
模块在使用前需要先导入 导入的语法如下
[from 模块名] import [模块|类|变量|函数|*] [as 别名]
常见的组合形式如:
import 模块名
from 模块名 import 类、变量、方法等
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名
import 模块名
基本语法:
import 模块名
import 模块名1,模块名2
模块名.功能名()
案例:导入time模块
# 导入时间模块
import time
print("开始")
# 让程序睡眠1秒(阻塞)
print("结束")
制作自定义模块
python中已经帮我们实现了很多模块,不过有时候我们需要一些个性化的模块,这里就可以通过自定义模块实现
每个python文件都可以作为一个模块,模块的名字就是文件的名字
__all__
如果一个模块文件中有”__all__“变量,当使用‘from xxx import *'导入时,只能导入这个列表中的元素
if __name__ == '__main__': test_a(1,2)
只有当程序是直接执行的才会进入if内部,如果是被导入的,则if无法进入
注意事项:
不同模块,同名的功能,如果都被导入,那么后导入的会覆盖先导入的
什么是python包
从物理上来看,包就是一个文件夹,在该文件夹下包含了一个__init__.py文件,该文件夹可用于包含多个模块文件,从逻辑上看,包的本质依然是模块
包的作用:当我们的模块文件越来越多时,包可以帮助我们管理这些模块,包的作用就是包含多个模块,包的本质依然是模块
快速入门
步骤如下:
新建包”my_package"
新建包内模块:“my_module1"和”my_module2"
模块内代码如下
导入包
方式一:
import 包名.模块名
包名.模块名.目标
导入包
方式二:
注意:必须在__init__.py文件中添加__all__=[],控制允许导入的模块列表
from 包名 import *
模块名.目标
1.什么是python的包
包就是一个文件夹,里面可以存放许多python的模块(代码文件),通过包,在逻辑上将一批模块归为一类,方便使用
2.__init__.py文件的作用
创建包会默认自动创建的文件,通过这个文件来表示一个文件夹是python的包,而非普通的文件夹
3.__all__变量的作用
同模块中学习到的是一个作用,控制 import *能够导入的内容
什么是第三方包
包可以包含一堆的python模块,而每个模块又包含许多的功能
所以,我们可以认为:一个包,就是一堆同类型功能的集合体
在python程序的生态中,有许多非常多的第三方包
科学计算中常用的:numpy包
数据分析中常用的:pandas包
大数据计算中常用到的:pyspark、apache-flink包
图形可视化常用的:matplotlib、pyecharts包
人工智能常用的:tensorflow等
安装第三方包-pip
pip install 包名称
即可通过网络快速安装第三方包
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
什么是json
json是一种轻量级的数据交互格式。可以按照json指定的格式去组织和封装数据
json本质上是一个带有特定格式的字符串
主要功能:json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互,类似于:
国际通用语言-英语
中国56个民族不同地区的通用语言-普通话
json有什么用
各种编程语言存储数据的容器不尽相同,在python中有字典dict这样的数据类型,而其他语言可能没有对应的字典
为了让不同的语言都能够相互通用的互相传递数据,json就是一种非常良好的中转数据格式
json格式数据转化
json数据的格式可以是
{"name":"admin","age":18}
也可以是:
[{"name":"admin","age":18},{"name":"root","age":16},{"name":"张三","age":20}]
python数据和json数据的相互转化
#导入json模块
#准备符号格式json格式要求的是python数据
data=[{"name":"老王","age":16},{"name":"张三","age":20}]
# 通过json.dumps(data)方法把python数据转化为了json数据
data = json.dumps(data)
# 通过json.loads(data)方法把json数据转化为了python数据
data = json.loads(data)
pyecharts模块
如果想要做出数据可视化效果图,可以jiezhupyecharts模块来完成
概况:
pyecharts的入门使用
基础折线图
# 导包,导入line功能固件折线图对象
from pyecharts.charts import Line
# 得到折线图对象
line = Line()
# 添加x轴数据
line.add_xaxis(["中国","美国","英国"])
# 添加y轴数据
line.add_yaxis("GDP",["中国","美国","英国"])
# 生成图表
line.render()
pyecharts有哪些配置选项
pyecharts模块中有很多的配置选项,常用到2个类别的选项
全局配置选项
系列配置选项
set_global_opts方法
这里全局配置选项可以通过set_global_opts方法来进行配置,相应的选项和选项的功能如下
通过bar构建基础柱状图
列表的sort方法
使用方式:
列表.sort(key=选择排序依据的函数,reverse=True|False)
参数key,是要求传入一个函数,表示将列表的每一个元素都传入函数中,返回排序的依据
参数reverse,是否反转排序结果,True表示降序,False表示升序
使用对象组织数据
1.在程序中设计表格,我们称之为:设计类(class)
class Student:
name = None # 记录学生姓名
2.在程序中打印生产表格,我们称之为:创建对象
#基于类创建对象
stu_1 = Student()
stu_2 = Student()
3.在程序中填写表格,我们称之为:对象属性赋值
stu_1.name="周杰伦"
stu_2.name="林俊杰"
类的定义和使用
class 类名称:
类的属性
类的行为
类的属性:定义在类中的变量(成员变量)
类的行为:定义在类中的函数(成员方法)
成员方法的定义语法:
def 方法名(self,形参1,......形参n):
方法体
self关键字是成员方法定义的时候,必须填写的
它用来表示类对象自身的意思
当我们使用类对象调用方法的是,self会自动被python传入
在方法内部,想要访问类的成员变量,必须使用self
类只是一种程序内的“设计图纸”,需要基于图纸产生实体(对象),才能正常工作,这种套路,称之为:面向对象编程
构造方法
python类可以使用:__init__()方法,称之为构造方法
可以实现:
在创建类对象(构造类)的时候,会自动执行
在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用
python类可以使用:__init__()方法,称之为构造方法
可以实现:
在创建类对象(构造类)的时候会自动执行
在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用
魔术方法
内置的类方法,各自有各自特殊的功能,这些内置方法我们称之为魔术方法
__str__:字符串方法
__lt__:小于、大于符号比较
__le__:小于等于、大于等于符号比较
__eq__:==符号比较
内存地址没有多大作用,我们可以通过__str__方法,控制类转换为字符串的行为
方法名:__str__
返回值:字符串
内容:自行定义
__lt__小于符号比较方法
直接对2个对象进行比较是不可以的
方法名:__lt__
传入参数:other,另一个类对象
返回值:True或False
内容:自行定义
方法名:__eq__ 比较运算符实现方法
传入参数:other,另一个类对象
返回值:True或False
内容:自行定义
如果没有实现__eq__方法的话,比较的是内存地址
私有成员
既然现实事物有不公开的属性和行为,那么作为现实事物在程序中映射的类,也应该支持
类中提供了私有成员的形式来支持
私有成员变量
私有成员方法
私有成员变量:变量名以__开头
私有成员方法:方法名以__开头
使用私有成员
私有成员无法被类对象使用,但是可以被其他的成员使用
封装的概念:将现实世界事物在类中描述为属性和方法,即为封装
私有成员的访问限制
类对象无法访问私有成员
类中的其他成员可以访问私有成员
私有成员的意义:在类中提供仅供内部使用的属性和方法,而不对外开放(类对象无法使用)
单继承
继承的写法
class 类名(父类名):
类内容体
继承分为:单继承和多继承
继承表示:将从父类那里继承(复制)来成员变量和成员方法(不含私有)
class 类名(父类1,父类2,...父类n):
类内容体
多继承注意事项
多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级
即:先继承的保留,后继承的被覆盖
pass的作用
复写
子类继承父类成员属性和成员方法后,如果对其不满意,可以进行复写
即:在子类中重新定义同名的属性或方法即可
调用父类同名成员
一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员
如果需要使用被复写的父类的成员,需要特殊的调用方式:
方式1:调用父类成员
使用成员变量:父类名.成员变量
使用成员方法:父类名.成员方法(self)
方式2:使用super()调用父类成员
使用成员变量:super()成员变量
使用成员方法:super()成员方法()
类型注解
ctrl+p可以弹出相关的提示
为什么需要类型注解
pycharm无法通过代码确定应传入什么类型,我们需要使用类型注解
类型注解:在代码中设计数据交互的地方,提供数据类型的注解(显式的说明)
主要功能:
帮助第三方IDE工具(如pycharm)对代码进行类型推断,协助做代码提示
帮助开发者自身对变量进行类型注释
支持:
变量的类型注解
函数(方法)形参列表和返回值的类型注解
类型注解的语法
为变量设置类型注解
基础语法:变量:类型
var_1:int = 10
var_2:float = 3.1415926
var_3:bool = True
var_4:str="itheima"
类对象类型注解
class Student:
pass
stu:Student = Student()
基础容器类型注解
my_list :list = [1,2,3]
my_tuple:tuple = (1,2,3)
my_set:set={1,2,3}
my_dict:dict={"itheima":666}
my_str:str = "itheima"
容器类型详细注解
my_list:list[int] =[1,2,3]
my_tuple:tuple[str,int,bool]=("itheima",666,True)
my_set:set[int]={1,2,3}
my_dict:dict[str,int]={"itheima":666}
注意:
元组类型设置类型详细注解,需要将每一个元素都标记出来
字典类型设置类型详细注解,需要2个类型,第一个是key,第二个是value
类型注解的语法
除了使用 变量:类型,这种语法做注解外,也可以在注释中进行类型注解
语法:
# type:类型
class Student:
pass
var_1 = random.randint(1,10) # type:int
var_2 = json.loads(data) # type:dict[str,int]
var_3 = func() # type:Student
为变量设置注解,显示的变量定义,一般无需注解:
my_list :list = [1,2,3]
my_tuple:tuple = (1,2,3)
my_set:set={1,2,3}
my_dict:dict={"itheima":666}
my_str:str = "itheima"
如图,就算不写注解,也明确的知晓变量的类型
一般,无法直接看出变量类型时会添加变量的类型注解
var_1 = random.randint(1,10) # type:int
var_2 = json.loads(data) # type:dict[str,int]
var_3 = func() # type:Student
并不会真正的对类型做验证和判断
函数(方法)的类型注解-形参注解
函数和方法的形参类型注解语法:
def 函数方法名(形参名:类型,形参名:类型,....):
pass
def add(x:int,y:int):
return x+y
def func(data:list):
pass
函数(方法)的类型注解-返回值注解
def 函数方法名(形参:类型,....,形参:类型)->返回值类型:
pass
Union类型
my_list:list[int] =[1,2,3]
my_dict:dict[str,int] = {"age":11,"num":3}
使用Union[类型,.....,类型]
可以定义联合类型注解
多态
多态,指的是:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态
同样的行为(函数),传入不同的对象,得到不同的状态
多态常常作用在继承关系上
比如
函数(方法)形参声明接受父类对象
实际传入父类的子类对象进行工作
即:
以父类做定义声明
以子类做实际工作
用以获得同一个行为,不同的状态
抽象类(接口)
父类用来确定有哪些方法
具体的方法实现,由子类自行决定
这种写法,就叫做抽象类(也可以称之为接口)
抽象类:含有抽象方法的类称之为抽象类
抽象方法:方法体是空实现的(pass)称之为抽象方法
抽象类就好比定义了一个标准,包含了一些抽象的方法,要求子类必须实现
class AC:
def cool_wind(self):
pass
什么是多态
多态指的是,同一个行为,使用不同的对象获得不同的状态
如:定义函数(方法),通过类型注解声明需要父类对象,实际传入子类对象进行工作,从而获得不同的工作状态
什么是抽象类(接口)
包含抽象方法的类,称之为抽象类。抽象方法是指:没有具体实现的方法(pass)称之为抽象方法
抽象类的作用
多用于顶层设计(设计标准),以便子类做具体实现
也是对子类的一种软性约束,要求子类必须复写(实现)父类的一些方法
无处不在的数据库
使用数据库软件去获取库-》表-》数据,这种数据组织、存储的能力
并借助sql语言,完成对数据的增删改查等操作
show databases:查看有哪些数据库
use 数据库名 使用某个数据库
show tables 查看数据库内有哪些表
exit 退出mysql的命令行环境
数据定义:DDL(data definition language)
库的创建删除、表的创建删除等
数据操纵:DML(data manipulation language)
新增数据、删除数据、修改数据等
数据控制:DCL(data control language)
新增用户、删除用户、密码修改、权限管理
数据查询:DQL(data query language)
基于需求查询和计算数据
SQL是不区分大小写的
SQL可以单行或多行书写,最后以;结束
SQL支持注释:
单行注释:--注释内容(--后面一定要有一个空格)
单行注释:# 注释内容(# 后面可以不加空格,推荐加上)
多行注释:/*注释内容*/
DDL-库管理
查看数据库
show databases;
使用数据库
use 数据库名称;
创建数据库
create database 数据库名称 [CHARSET UTF8];
删除数据库
DROP DATABASE 数据库名称;
查看当前使用的数据库
SELECT DATDABASE();
DDL-表管理
查看有哪些表
show table; 注意:需要先选择数据库哦
创建表
create table 表名称(
列名称 列类型,
列名称 列类型,
.......
);
列类型有:
int --整数
flaot --浮点数
varchar(长度) --文本,长度为数字,做最大长度限制
date --日期类型
timestamp --时间戳类型
掌握DML:INSERT数据插入
掌握DML:DELETE数据删除
掌握DML:UPDATE数据更新
DML是指数据操作语言
基础语法
insert into 表[(列1,列2,.....列n)] values (值1,值2,......,值n)[,(值1,值2,....值n)]
数据删除 delete
基础语法:
delete from 表名称 [where 条件判断]
条件判断:列 操作符 值
操作符:= < > <= >= != 等等,
如 id = 5 id < 3 id >=6 id != 5
数据更新 update
基础语法
update 表名 set 列=值 [where 条件判断];
注意事项
字符串的值,出现在sql语句中,必须要用单引号包围起来
分组聚合
分组聚合的应用常见非常多,如:统计班级中,男生和女生的人数
这种需求就需要:
按照性别分组
统计每个组的人数
这就称之为:分组聚合
基础语法:
select 字段|聚合函数 from 表 [where 条件] group by 列
聚合函数有:
-sum(列)求和
-AVG(列)求平均值
-MIN(列)求最小值
-MAX(列)求最大值
-COUNT(列|*)求数量
select database();
create table student(
id int,
name varchar(10),
age int
);
insert into student(id) values(1),(2),(3);
insert into student(id,name,age) values(4,'周杰伦',31),(5,'林俊杰',33);
delete from student where id = 1;
update student set name = '张学友' where id = 4;
select gender,avg(age) from student group by gender
当group by里面写了谁,就在select语句里出现谁
分组聚合的注意事项:
group by中出现了哪个列,哪个列才能出现在select中的非聚合中
掌握DQL:对查询结果进行排序分页
结果分页限制
可以使用limit关键字,对查询结果进行数量限制或分页显示
select 列|聚合函数|* from 表
where ...
order by ...[ASC|DESC]
limit n[,m]
执行顺序:
from -> where -> group by和聚合函数 ->select ->order by ->limit
pymysql
除了使用图形化工具以外,我们也可以使用编程语言来执行sql从而操作数据库
在python中,使用第三方库:pymysql来完成对mysql数据库的操作
安装:
pip install pymysql
from pymysql import Connection # 构建到mysql数据库的连接 conn = Connection( host="localhost", #主机名(IP) port=3306, # 端口 user='root', # 账户 password="byj021119" # 密码 ) print(conn.get_server_info()) # 执行非查询性质sql cursor = conn.cursor() # 获取到游标对象 # 选择数据库 conn.select_db("zuel") # 执行查询性质sql # cursor.execute("create table test_pymysql(id int);") cursor.execute("select * from student") results = cursor.fetchall() for r in results: print(r) # 关闭连接 conn.close()
commit提交
pymysql在执行数据插入或其他产生数据更改的sql语句时,默认是需要提交更改的,即,需要通过代码确认这种更改行为
通过连接对象.commit()方法即可确认此行为
python操作(138综合案例没有做)
pyspark的执行环境入口对象是:类SparkContext的类对象
sparkcontext类对象,是pyspark编程中一切功能的入口
pyspark的编程,主要分为如下三大步骤
RDD:弹性分布式数据集(Reslilient Distributed Datasets)
python数据容器转RDD对象
pyspark支持通过sparkcontext对象的parallelize成员方法,将
List
tuple
set
dict
str
转换为pyspark的rdd对象
注意:
字符串会被拆分出一个个的字符,存入rdd对象
字典仅有的key会被存入rdd对象
读取文件转rdd对象
pyspark也支持通过sparkcontext入口对象,来读取文件,来构建出rdd对象
rdd对象称之为分布式弹性数据集,是pyspark中数据计算的载体,它可以:
提供数据存储
提供数据计算的各种方法
数据计算的方法,返回值依旧是rdd(rdd迭代计算)
后续对数据进行各类计算,都是基于rdd对象进行
如何输入数据到spark(即得到rdd对象)
通过sparkcontext的parallelize成员方法,将python数据容器转换为rdd对象
通过sparkcontext的textfile成员方法,读取文本文件得到rdd对象
map方法
功能:map算子,是将rdd的数据一条条处理(处理的逻辑基于map算子中接收的处理函数)返回新的rdd
接受一个处理函数,可用lambda表达式快速编写
对rdd内的元素逐个处理,并返回一个新的rdd
链式调用
对于返回值是新rdd的算子,可以通过链式调用的方法多次调用算子
flatMap算子
功能:对rdd执行map操作,然后进行解除嵌套操作
reduceByKey算子
功能:针对KV型rdd,自动按照key分组,然后根据提供的聚合逻辑,完成组内数据(value)的聚合操作
用法:
rdd.reduceByKey(func)
# func:(V,V) -> V
接受2个传入参数(类型要一致),返回一个返回值,类型和传入要求一致
Filter
功能:过滤想要的数据进行保留
语法:
rdd.filter(func)
func:(T) -> bool 传入1个参数进来随意类型,返回值必须是true or false
filter算子
接受一个处理函数,可用lambda快速编写
函数对rdd数据逐个处理,得到true的保留至返回值的rdd中
distinct算子
功能:对rdd数据进行去重,返回新rdd
语法:
rdd.distinct() 无需传参
sortBy算子
功能:对rdd数据进行排序,基于你指定的排序依据
语法:
rdd.sortBy(func,ascending=False,numPartitions=1)
# func:(T)->U:告知按照rdd中的哪个数据进行排序,比如lambda x:x[1]表示按照rdd中的第二列元素进行排序
# ascending True升序 False 降序
# numPartitions:用多少分区排序
sortBy算子
接收一个处理函数,可用lambda快速编写
函数表示用来决定排序的依据
可以控制升序或降序
全局排序需要设置分区数为1
collect算子
功能:将rdd各个分区内的数据,统一收集到driver中,形成一个list对象
用法:
rdd.collect()
返回值是一个list
reduce算子
功能:对rdd数据集按照你传入的逻辑进行聚合
语法:
rdd.reduce(func)
# func:(T,T)->T
# 2参数传入1个返回值,返回值和参数要求类型一致
take算子
功能:取rdd的前n个元素,组合成list返回
用法:sc.parallelize([3,2,1,4,5,6]).take(5)
count算子
功能:计算rdd有多少条数据,返回值是一个数字
用法:
sc.parallelize([1,2,3,4,5]).count()
saveAsTextFile算子
功能:将rdd的数据写入文本文件中
支持本地写出,hdfs等文件系统
注意事项
调用保存文件的算子,需要配置hadoop依赖
下载hadoop安装包
修改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 = c.parallelize([1,2,3,4,5],numSlices=1)
rdd1 = sc.parallelize([1,2,3,4,5],1]
rdd输出到文件的方法
rdd.saveAsTextFile(路径)
输出的结果是一个文件夹
有几个分区就输出多少个结果文件夹
闭包
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包
修改外部函数变量的值
需要使用nonlocal关键字修饰外部函数的变量才可在内部函数中修改它
闭包的注意事项
优点,使用闭包可以让我们得到
无需定义全局变量即可实现通过函数,持续访问、修改某个值
闭包使用的变量所用于在函数内,难以被错误的调用修改
缺点:
由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存
什么是闭包:
定义双层嵌套函数,内层函数可以访问外层函数的变量
将内存函数作为外层函数的返回,此内层函数就是闭包函数
nonlocal关键字的使用
在闭包函数(内部函数中)想要修改外部函数的变量值
需要用nonlocal声明这个外部变量
装饰器
装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能
装饰器的一般写法(闭包写法)
def outer(func):
def inner():
print("我要睡觉了")
func()
print("我要起床了")
return inner
装饰器的语法糖写法
@outer
def sleep():
import random
import time
print("睡眠中...")
time.sleep(random.randint(1,5))
sleep()
什么是装饰器
装饰器就是使用创建一个闭包函数,在闭包函数内调用目标函数,可以达到不改动目标函数的同时,增加额外的功能
设计模式
设计模式是一种编程套路,可以极大的方便程序的开发
单例、工厂模式
建造者、责任链、状态、备忘录、解释器、访问者、观察者、中介、模板、代理模式
单例模式
创建类的实例后,就可以得到一个完整的、独立的类对象
单例模式
定义:保证一个类只有一个实例,并提供一个访问它的全局访问点
适用场景:当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时
class StrTools:
pass
设计模式就是一种编程套路
使用特定的套路得到特定的效果
什么是单例设计模式
单例模式就是对一个类,只获取其唯一的类实例对象,持续复用它
节省内存
节省创建对象的开销
工厂模式
当需要大量创建一个类的实例的时候,可以使用工厂模式
即,从原生的使用类的构造去创建对象的形式
迁移到,基于工厂提供的方法去创建对象的形式
class Person:
pass
class Student(Person):
pass
class Teacher(Person):
pass
class Factory:
def get_person(self,p_type):
if p_type == 'w':
return Worker()
elif p_type == 's':
return Student()
else:
return Teacher()
factory = Factory()
worker = factory.get_person('w')
stu = factory.get_person('s')
teacher = factory.get_person('t')
worker = Worker()
stu = Student()
teacher = Teacher()
使用工厂类的get_person()方法去创建具体的类对象
优点:
大批量创建对象的时候有统一的入口,易于代码维护
当发生修改,仅修改工厂类的创建方法即可
符合现实世界的模式,即由工厂来制作产品(对象)
什么是工厂模式
将对象的创建由使用原生类本身创建
转换到由特定的工厂方法来创建
好处
大批量创建对象的时候有统一的入口,易于代码维护
当发生修改,仅修改工厂类的创建方法即可
符合现实世界的模式,即由工厂来制作产品(对象)
进程、线程
现代操作系统都是支持多任务的操作系统
进程:就是一个程序,运行在系统之上,那么便称这个程序为一个运行进程,并分配进程id方便系统管理
线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位
进程好比一家公司,是操作系统对程序进行运行管理的单位
线程好比公司的员工,进程可以有多个线程(员工),是进程实际的工作者
操作系统可以运行多个进程,即多任务运行
一个进程内可以运行多个线程,即多线程运行
注意点:
进程之间是内存隔离的,即不同的进程拥有各自的内存空间。这就类似于不同的公司拥有不同的办公场所
线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程拥有的内存空间的,这就好比,公司员工之间是共享公司的办公场所
并行执行
并行执行的意思指的是同一时间做不同的工作
进程之间就是并行执行的,操作系统可以同时运行好多程序,这些程序都是并行在执行
除了进程外,线程也是可以并行执行的
比如一个python程序,完全可以做到
一个线程在输出:你好
一个线程在输出hello
像这样一个程序在同一时间做两件乃至多件不同的事情,我们就称之为:多线程并行执行
一个进程内的多个线程同时在运行,称之为:多线程并行执行
threading模块
绝大多数编程语言,都允许多线程编程,python也不例外
python的多线程可以通过threading模块来实现
import threading
thread_obj = threading.Thread([group[,target[,name[,args[,kwargs]]]]])
- group:暂时无用,未来功能的预留参数
- target:执行的目标任务名
- args:以元组的方式给执行任务传参
- kwargs:以字典方式给执行任务传参
- name:线程名,一般不用设置
需要传参的话可以通过:
args参数通过元组(按参数顺序)的方式传参
或使用kwargs参数用字典的形式传参
Socket
socket(简称 套接字)是进程之间通信的一个工具,好比现实生活中的插座,所有的家用电器想要工作都是基于插座进行,进程之间想要进行网络通信需要socket
socket负责进程之间的网络数据传输,好比数据的搬运工
2个进程之间通过socket进行相互通讯,就必须有服务端和客户端
socket服务端:等待其他进程的连接、可接受发来的消息,可以回复消息
socket客户端:主动连接服务端、可以发送消息、可以接收回复
socket服务端编程
1.创建socket对象
import socket
socket_server = socket.socket()
2.绑定socket_server到指定ip和地址
socket_server.bind(host,port)
3.服务器端开始监听端口
socket_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客户端编程
主要分为如下几个步骤
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(semd_msg)
recv_data = socket_client.recv(1024) # 1024是缓冲区大小,一般1024即可
# recv方法是阻塞式的,即不接收到返回,就卡在这里等待
print("服务端回复消息为",recv_data,decode("UTF-8")) #接受的消息需要通过UTF-8解码为字符串
5.关闭连接
socket_client.close() # 最后通过close关闭连接
学习目标:
了解什么是正则表达式
掌握re模块的基础使用
正则表达式:规则表达式,是使用单个字符串来描述、匹配某个句法规则的字符串,常常被用来检索、替换那些符合某个模式(规则)的文本
正则表达式就是使用:字符串定义规则,并通过规则去验证字符串是否匹配
正则的3个基础方法
python正则表达式,使用re模块,并基于re模块中三个基础方法来做正则匹配
分别是:match、search、findall三个基础方法
re.match(匹配规则,被匹配字符串)
从被匹配字符串开头进行匹配,匹配成功返回匹配对象(包含匹配的信息),匹配不成功返回空
re.search(匹配规则,被匹配字符串)
搜索整个字符串,找出匹配的。从前往后,找到第一个后,就停止,不会继续向后
正则的三个基础方法
findall(匹配规则,被匹配字符串)
匹配整个字符串,找出全部匹配项
找不到返回空列表
掌握正则表达式的各类元字符规则
了解字符串的r标记作用
.:匹配任意1个字符(除了\n,\.匹配点本身)
[]:匹配[]中列举的字符
\d:匹配数字,即0-9
\D:匹配非数字
\s:匹配空白,即空格、tab键
\S:匹配非空白
\w:匹配单词字符,即a-z、A-Z、0-9
\W:匹配非单词字符
示例:
* 匹配前一个规则的字符出现0至无数次
+ 匹配前一个规则的字符出现1至无数次
?匹配前一个规则的字符出现0次或1次
{m} 匹配前一个规则的字符出现m次
{m,}匹配前一个规则的字符吹西安最少m次
{m,n} 匹配前一个规则的字符出现m到n次
边界匹配:
^ 匹配字符串开头
$ 匹配字符串结尾
\b 匹配一个单词的边界
\B 匹配非单词边界
分组匹配
| 匹配左右任意一个表达式
() 将括号中字符作为一个分组
递归在编程中是一种非常重要的算法
递归:即方法(函数)自己调用自己的一种特殊编程写法