b站黑马程序员python基础学习

   python的安装

第一个python程序

 打开CMD(命令提示符)程序,输入Python并回车

然后,在里面输入代码回车即可立即执行

 Python 解释器

我们可以将代码,写入一个以”.py”结尾的文件中,使用python命令去运行它。 

 Python 开发环境 

Python程序一般常见的3种开发环境:

Python解释器环境内,执行单行代码

使用Python解释器程序,执行Python代码文件

使用第三方IDE(集成开发工具),如PyCharm软件,开发Python程序

指定工程路径以及选择Python解释器

创建一个Python代码文件 ,名称test.py

 

 常用快捷键

ctrl + alt + s : 打开软件设置
ctrl + d :复制当前行代码
shift + alt + \ 将当前行代码上移或下移
crtl + shift + f10 : 运行当前代码文件
shift + f6 :重命名文件
ctrl + a : 全选
ctrl + c\v\x : 复制、粘贴、剪切
ctrl + f : 搜索
Python基础语法

 字面量 


常见的字面量类型

3类:整数、浮点数、字符串

 基于print语句完成各类字面量的输出

print(字面量),如:

print(10) ,输出整数 10
print(13.14) ,输出浮点数 13.14
Print(“ 周报 ”) 输出字符串 周报

 Python的注释

单行注释的方法

通过 # 号定义,在#号右侧的所有内容均作为注释

建议在#号和注释内容之间,间隔一个空格

单行注释一般用于对一行或一小部分代码进行解释


多行注释的方法

通过一对三个引号来定义("""注释内容"""),引号内部均是注释,可以换行

 Python的变量

变量的语法:  变量名称 = 变量的值

变量的目的是存储运行过程的数据

存储的目的是为了:重复使用

 变量的特征:   变量的值可以改变

 

数据类型 

string

字符串类型

用引号引起来的数据都是字符串

int

整型(有符号)

数字类型,存放整数 如 -1,10, 0

float

浮点型(有符号)

数字类型,存放小数 如 -3.14, 6.66


验证数据的类型的方法:     通过type()语句验证

语法:

type(被查看类型的数据)

1. print语句中,直接输出类型信息:

 

 2. 用变量存储type()的结果(返回值)

 3.使用type()语句,来查看变量中存储的数据类型信息

 

   数据类型转换

 数据类型常见的转换语句

 

      标识符

标识符的定义:

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


标识符的命名规则

内容限定
(中文、英文、数字、下划线)
大小写敏感
不可使用关键

常用关键字


 变量的命名规范

见名知意

下划线命名法

英文字母全小写

  常用的运算符

算数(数学)运算符

+(加)

-(减) 

*(乘)

/(除)

//(取整数)

%(取余)

**(指数)

           


 赋值运算符

                          


复合赋值运算符

 字符串的扩展

字符串的扩展

字符串在Python中有多种定义形式

1.单引号定义法

2.双引号定义法

3.三引号定义法

                              


 字符串的拼接

 

完成字符串拼接的方法

使用“+”号连接字符串变量或字符串字面量即可

字符串格式化

1.  字符串格式化的语法

            "%占位符" % 变量

        2. 常用占位符

字符串:%s
整数 :   %d
浮点数 :   %f

其中的,%s

表示:我要占位
s   表示:将变量变成字符串放入占位的地方

 


最长用的3类数据类型

%s      把内容转换成字符串,放入占位位置

%d      把内容转换成整数,放入占位位置

%f       把内容转换成浮点型,放入占位位置

 

 格式化的精度控制

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

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

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

示例:

%5d:表示将整数的宽度控制在5位,如数字11,被设置为5d,就会变成:[空格][空格][空格]11,用三个空格补足宽度。

%5.2f:表示将宽度控制为5,将小数点精度设置为2

小数点和小数部分也算入宽度计算。如,对11.345设置了%7.2f 后,结果是:[空格][空格]11.352个空格补足宽度,小数部分限制2位精度后,四舍五入为 .35

%.2f:表示不限制宽度,只设置小数点精度为2,如11.345设置%.2f后,结果是11.35

 

 

                            字符串格式化 - 快速写法 

快速格式化语法:   f"内容{变量}" 的格式来快速格式化

 字符串格式化 - 表达式的格式化

 

 

  


input函数的使用

1. input()语句的功能是,获取键盘输入的数据

2. 可以使用:input(提示信息),用以在使用者输入内容之前显示提示信息。

3. 要注意,无论键盘输入什么类型的数据,获取到的数据永远都是字符串类型

 

 


                Python判断语句


                    布尔类型和比较运算符 

 定义变量存储布尔类型数据

变量名称 = 布尔类型字面量

 

 比较运算符的使用

 


    if语句的基本格式

if语句的基本格式

If 要判断的条件:

         条件成立时,要做的事情


 

if语句的注意事项:

判断条件的结果一定要是布尔类型
不要忘记判断条件后的: 引号
归属于 if 语句的代码块,需在前方填充 4 个空格缩进

     if else 语句

1. if else 语句,其中
if 和其代码块,条件满足时执行
else 搭配 if 的判断条件,当不满足的时候执行

 

 

 

if else语句的注意事项:

else 不需要判断条件,当 if 的条件不满足时, else 执行
else 的代码块,同样要 4 个空格作为缩进

      if elif else语句

   if elif else语句的作用

可以完成多个条件的判断

 


 

 使用if elif else的注意点有:

elif 可以写多个
判断是互斥且有序的,上一个满足后面的就不会判断了
可以在条件判断中,直接写 input 语句,节省代码量
判断语句的嵌套

 嵌套语句的语法:


 简单嵌套:


 应用实例:   公司要发礼物,条件是:

    1. 必须是大于等于18岁小于30岁的成年人

    2. 同时入职时间需满足大于两年,或者级别大于3才可领取

如图:

if elif else 可以自由组合
满足缩进的要求即可


               python循环语句 

 while循环的语法格式

While 条件:

           条件满足时,做的事情1

           条件满足时,做的事情2

            …….


 


      while循环的基础案例

 设置一个范围1-100的随机整数变量,通过while循环,配合input语句,判断输入的数字是否等于随机数

1.无限次机会,直到猜中为止

2.每一次猜不中,会提示大了或小了

3.猜完数字后,提示猜了几次


     while循环的嵌套应用

循环嵌套的语法:

 

同判断语句的嵌套一样,循环语句的嵌套,要注意空格缩进。

基于空格缩进来决定层次关系

注意条件的设置,避免出现无限循环(除非真的需要无限循环 )

for循环的基础语法

for和while的区别:

除了while循环语句外,Python同样提供了for循环语句。

两者能完成的功能基本差不多,但仍有一些区别:

while 循环的循环条件是自定义的, 自行控制循环条件
for 循环是一种 轮询 机制,是对一批内容进行 逐个处理

for循环的语法:

for 临时变量 in 待处理数据集:

        循环满足条件时执行的代码

 

while循环不同,for循环是无法定义循环条件的。

只能从被处理的数据集中,依次取出内容进行处理。


  range语句

range语法:

for 临时变量 in 待处理数据集(可迭代对象):

        循环满足条件时执行的代码

range语句,获得一个简单的数字序列

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

range(5)取得的数据是:[0, 1, 2, 3, 4]

 

  掌握for循环的嵌套使用 

需要注意缩进,嵌套 for 循环同样通过缩进确定层次关系
for 循环和 while 循环可以相互嵌套使用

 


 使用continuebreak关键字控制循环 

continue关键字用于:中断本次循环,直接进入下一次循环

continue可以用于:    for循环和while循环,效果一致

break关键字用于:直接结束所在循环

break可以用于:    for循环和while循环,效果一致

 

 


函数的基础定义语法 

 函数的基础定义语法

def  函数名(传入参数):

       函数体

       return 返回值


 

  函数的参数 

作用:  在函数运行的时候,接受外部传入的数据 

函数定义中,提供的 x y ,称之为:形式参数(形参),表示函数声明将要使用 2 个参数
参数之间使用逗号进行分隔
函数调用中,提供的 5 6 ,称之为:实际参数(实参),表示函数执行时真正使用的参数值
传入的时候,按照顺序传入数据,使用逗号分隔

   练习案例:升级版自动查核酸

定义一个函数,名称任意,并接受一个参数传入(数字类型,表示体温)

在函数内进行体温判断(正常范围:小于等于37.5度),并输出如下内容 


函数返回值

语法:

def 函数(参数…):

         函数体

         return 返回

变量=函数(参数)


通过return关键字,就能像调用者返回数据


 None

None表示:空的、无实际意义的意思

函数返回的None,就表示,这个函数没有返回什么有意义的内容



      函数的说明文档

   函数的嵌套调用 

 

 

函数A中执行到调用函数B的语句,会将函数B全部执行完成后,继续执行函数A的剩余内容 

    变量的作用域(局部变量,全局变量)

 1.局部变量的定义

作用范围在函数内部,在函数外部无法使用

2. 全局变量的定义

在函数外面定义,这样的话在函数内部和外部均可使用

 


        数据容器

目的:  批量存储或批量使用多份数据 

类型:  list(列表)tuple(元组)str(字符串)set(集合)dict(字典)

   list(列表) 

基本语法

#字面量

[元素1,元素2,元素3,….]

#定义变量

变量名称=[元素1,元素2,元素3]

#定义空列表

变量名称=[]

变量名称=List()

列表内的每一个数据,称之为元素

以 [] 作为标识

列表内每一个元素之间用, 逗号隔开


 

 list的下标索引 

 

 从后向前,下标索引为:-1-2-3,依次递减。


 


 

 

  列表的常用操作(方法)

查找某元素的 下标

语法:列表.index(元素)

 index就是列表对象(变量)内置的方法(函数)

 


修改特定位置(索引)的元素值:

     语法:列表[下标] =

     可以使用如上语法,直接对指定下标(正向、反向下标均可)的值进行:重新赋值(修改)


插入元素:

     语法:列表.insert(下标, 元素),在指定的下标位置,插入指定的元素

 


追加元素1:

     语法:列表.append(元素),将指定元素,追加到列表的尾部

 

追加元素方式 2

     语法:列表.extend(其它数据容器),将其它数据容器的内容取出,依次追加到列表尾部


 •删除元素:

     语法1 del 列表[下标]

     语法2:列表.pop(下标)

 


列表的修改功能(方法)


列表的查询功能(方法

统计列表内,有多少元素

     语法:len(列表)


 list(列表)的遍历

 遍历

将容器内的元素依次取出,并处理,称之为遍历操作

 

 

while循环和for循环,都是循环语句,但细节不同:

在循环控制上:
while 循环 可以自定循环条件 ,并自行控制
for 循环 不可以自定循环条件 ,只可以一个个从容器内取出数据
在无限循环上:
while循环 可以 通过条件控制做到无限循环
for循环理论上 不可以 ,因为被遍历的容器容量不是无限的
在使用场景上:
while循环适用于任何想要循环的场景
for循环适用于,遍历数据容器的场景或简单的固定次数循环场景

 元组的定义格式

定义格式:

(元素, 元素, 元素, ......) 

 

列表有如下特点:

可以容纳多个数据
可以容纳不同类型的数据(混装)
数据是有序存储的(下标索引)
允许重复数据存在
不可以修改 (增加或删除元素等)
支持for循环
字符串的常见操作

 

 同元组一样,字符串是一个:无法修改的数据容器。

所以:

修改指定下标的字符  (如:字符串 [0] = “a”
移除特定下标的字符  (如:del 字符串[0]、字符串 .remove() 、字符串 .pop() 等)
追加字符等  (如:字符串 .append()

均无法完成。如果必须要做,只能得到一个新的字符串,旧的字符串是无法修改


查找特定字符串的下标索引值

     语法:字符串.index(字符串)


 •字符串的替换

     语法:字符串.replace(字符串1,字符串2

     功能:将字符串内的全部:字符串1,替换为字符串2

     注意:不是修改字符串本身,而是得到了一个新字符串哦


字符串的分割

     语法:字符串.split(分隔符字符串)

     功能:按照指定的分隔符字符串,将字符串划分为多个字符串,并存入列表对象中

 


 •统计字符串中某字符串的出现次数

     语法:字符串.count(字符串)

 


 •字符串的规整操作(去前后空格)

     语法:字符串.strip()

 


 •字符串的规整操作(去前后指定字符串)

     语法:字符串.strip(字符串)

 


操作                                                                                   说明

字符串[下标]                                                      根据下标索引取出特点位置字符

字符串.index(字符串)                                       查找给定自动的第一个匹配项的下标

字符串.replace(字符串1,字符串2)          字符串内的全部字符串1,替换为字符串2.不会修改原字符串

字符串.split(字符串)                                          对字符串进行分割

字符串.strip()                                             移除首位的空格和换行符或指定字符串

字符串.count(字符串)                                  统计字符串内字符串的出现次数

len(字符串)                                                    统计字符串的字符个数 


字符串有如下特点:

只可以存储字符串
长度任意(取决于内存大小)
支持下标索引
允许重复字符串存在
不可以修改 (增加或删除元素等)
支持for循环

基本和列表、元组相同

不同与列表和元组的在于:字符串容器可以容纳的类型是单一的,只能是字符串类型。

不同于列表,相同于元组的在于:字符串不可修改


 数据容器的切片

语法:序列[起始下标:结束下标:步长]

表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列

起始下标表示从何处开始,可以留空,留空视作从头开始
结束下标(不含)表示何处结束,可以留空,留空视作截取到结尾
步长表示,依次取元素的间隔
步长 1 表示,一个个取元素
步长 2 表示,每次跳过 1 个元素取
步长 N 表示,每次跳过 N-1 个元素取
步长为负数表示,反向取(注意,起始下标和结束下标也要反向标记)

 

 

 

    集合

    操作                                                                                说明

 集合.add(元素)                                                      集合内添加一个元素

集合.remove(元素)                                                   移除集合内指定的元素

集合.pop()                                                              从集合中随机取出一个元素

集合.clear()                                                              将集合清空

集合1.different(集合2)                      得到一个新集合,内含2个集合的差集  原有的2个集合内容不变

集合1.different_update(集合2)            在集合1中,删除集合2中存在的元素. 集合1被修改,集合2不变

集合1.union(集合2)                   得到1个新集合,内含2个集合的全部元素,原有的2个集合的内容不变

len(集合2)                                       得到一个整数,记录了集合的元素数量


语法:集合.add(元素)。将指定元素,添加到集合内

     结果:集合本身被修改,添加了新元素


移除元素

     语法:集合.remove(元素),将指定元素,从集合内移除

     结果:集合本身被修改,移除了元素


从集合中随机取出元素

     语法:集合.pop(),功能,从集合中随机取出一个元素

     结果:会得到一个元素的结果。同时集合本身被修改,元素被移除

 


 •清空集合

     语法:集合.clear(),功能,清空集合

     结果:集合本身被清空


消除 2 个集合的差集

     语法:集合1.difference_update(集合2)

     功能:对比集合1和集合2在集合1内,删除和集合2相同的元素。

     结果:集合1被修改,集合2不变

 


 •取出2个集合的差集

     语法:集合1.difference(集合2),功能:取出集合1和集合2的差集(集合1有而集合2没有的)

     结果:得到一个新集合,集合1和集合2不变

 


2 个集合合并

     语法:集合1.union(集合2)

     功能:将集合1和集合2组合成新集合

     结果:得到新集合,集合1和集合2不变

 


 •查看集合的元素数量

     语法:len(集合)

     功能:统计集合内有多少元素

     结果:得到一个整数结果

      掌握字典的定义格式

 字典同集合一样,不可以使用下标索引

但是字典可以通过Key值来取得对应的Value


从字典中基于key获取value

 


字典的嵌套

 


嵌套字典中获取数据

 


  字典的常用操作说明

 操作                                                                                            说明

 字典[key]                                                                     获取指定key对应的value值

字典[key]=value                                                           添加或者更新新的键值对

字典.pop(key)                                                取出key对应的value并在字典内删除此key的键值对

字典.clear()                                                                   清空字典

字典.keys()                                                 获取字典的全部key, 可用于for循环遍历字典

len(字典)                                                                    计算字典内的元素数量


字典的增加

 


字典的更新


字典删除


清空字典

  语法:字典.clear(),结果:字典被修改,元素被清空


获取全部的 key

  语法:字典.keys(),结果:得到字典中的全部Key

 

 


遍历字典

  语法:for key in 字典.keys()

 


计算字典内的全部元素(键值对)数量

  语法:len(字典)

  结果:得到一个整数,表示字典内元素(键值对)的数量

 


经过上述对字典的学习,可以总结出字典有如下特点:

可以容纳多个数据
可以容纳不同类型的数据
每一份数据是 KeyValue 键值对
可以通过 Key 获取到 Value Key 不可重复(重复会覆盖)
不支持下标索引
可以修改 (增加或删除更新元素等)
支持for循环,不支持 while 循环

数据容器对比总结

数据容器可以从以下视角进行简单的分类:

是否支持下标索引
支持:列表、元组、字符串 - 序列类型
不支持:集合、字典 - 非序列类型
是否支持重复元素:
支持:列表、元组、字符串 - 序列类型
不支持:集合、字典 - 非序列类型
是否可以修改
支持:列表、集合、字典
不支持:元组、字符串

容器特点对比


1. 基于各类数据容器的特点,它们的应用场景如下:
列表:一批数据,可修改、可重复的存储 场景
元组:一批数据,不可修改、可重复的存储 场景
字符串:一串字符串的存储 场景
集合:一批数据,去重存储 场景
字典:一批数据,可用 Key 检索 Value 的存储场景

数据容器的通用操作

Len(容器)   统计容器的元素个数 


max(容器)

统计容器的最大元素


min(容器)

统计容器的最小元素


list(容器)

将给定容器转换为列表

tuple(容器)

将给定容器转换为元组

str(容器)

将给定容器转换为字符串

set(容器)

将给定容器转换为集合


通用排序功能

sorted(容器, [reverse=True])

将给定容器进行排序

注意,排序后都会得到列表(list)对象


 函数的进阶

函数的多个返回值

按照返回值的顺序,写对应顺序的多个变量接收即可

变量之间用逗号隔开

支持不同类型的数据return


函数的多种参数适用形式 

位置参数:调用函数时根据函数定义的参数位置来传递参数

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

作用: 可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求.

 


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

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


 不定长参数:不定长参数也叫可变参数. 用于不确定调用的时候会传递多少个参数(不传参也可以)的场景.

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

 

位置不定长传递以*号标记一个形式参数,以元组的形式接受参数,形式参数一般命名为args

      · 关键字不定长传递以**号标记一个形式参数,以字典的形式接受参数,形式参数一般命名为kwargs


   函数作为参数传递 

函数compute,作为参数,传入了test_func函数中使用。

test_func 需要一个函数作为参数传入,这个函数需要接收 2 个数字进行计算,计算逻辑由这个被传入函数决定
compute 函数接收 2 个数字对其进行计算, compute 函数作为参数,传递给了 test_func 函数使用
最终,在 test_func 函数内部,由传入的 compute 函数,完成了对数字的计算操作

所以,这是一种,计算逻辑的传递,而非数据的传递。

就像上述代码那样,不仅仅是相加,相见、相除、等任何逻辑都可以自行定义并作为函数传入。

 

 


   lambda匿名函数的语法 

 函数的定义中

def 关键字,可以定义 带有名称 的函数
lambda 关键字,可以 定义匿名 函数(无名称)

有名称的函数,可以基于名称重复使用

无名称的匿名函数,只可临时使用一次

匿名函数定义语法: lambda 传入参数: 函数体(一行代码)


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

 

 


  Python文件操作 

编码的概念: 

什么是编码?

编码就是一种规则集合,记录了内容和二进制间进行相互转换的逻辑。

编码有许多中,我们最常用的是UTF-8编码


为什么需要使用编码?

计算机只认识01,所以需要将内容翻译成01才能保存在计算机中。

同时也需要编码, 将计算机保存的01,反向翻译回可以识别的内容 


open()打开函数

Python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下

open(name,mode,encoding)

name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)

mode:设置打开文件的模式(访问模式):只读、写入、追加等。

encoding:编码格式(推荐使用UTF-8

read()方法:

 

 


readlines()方法:

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


readline()方法:一次读取一行内容 

 


close() 关闭文件对象


with open 语法

        写操作快速入门

写操作快速入门

# 1. 打开文件

f = open('python.txt', 'w')

# 2.文件写入

f.write('hello world')

# 3. 内容刷新

f.flush()

注意:

p 直接调用 write ,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区
p 当调用 flush 的时候,内容会真正写入文件

 


w 模式,文件不存在,会创建新文件
w 模式,文件存在,会清空原有内容
close() 方法,带有 flush() 方法的功能

   文件的追加 

a 模式,文件不存在,会创建新文件
a 模式,文件存在,会在原有内容后面继续写入
可以使用 ”\n” 来写出换行符

 

 异常

当检测到一个错误时,Python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的异常, 也就是我们常说的BUG

异常的捕获方法 

基本语法:

try:

    可能发生错误的代码

except:

    如果出现异常执行的代码

 


捕获多个异常

try:

    print(1/0)

except (NameError, ZeroDivisionError):

    print('ZeroDivision错误...')


捕获异常并输出描述信息

try:

    print(num)

except (NameError, ZeroDivisionError) as e:

    print(e)


捕获所有异常

try:

    print(name)

except Exception as e:

    print(e)


异常else

else表示的是如果没有异常要执行的代码

try:

    print(1)

except Exception as e:

    print(e)

else:

    print('我是else,是没有异常的时候执行的代码')


异常的finally

finally表示的是无论是否异常都要执行的代码,例如关闭文件。

try:

    f = open('test.txt', 'r')

except Exception as e:

    f = open('test.txt', 'w')

else:

    print('没有异常,真开心')

finally:

    f.close()

  异常的传递

 利用异常具有传递性的特点, 当我们想要保证程序不会因为异常崩溃的时候,

就可以在main函数中设置异常捕获, 由于无论在整个程序哪里发生异常, 最终都

会传递到main函数, 这样就可以确保所有的异常都会被捕获

   Python模块

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


模块的作用:  python中有很多各种不同的模块, 每一个模块都可以帮助我

们快速的实现一些功能, 比如实现和时间相关的功能就可以使用time模块

我们可以认为一个模块就是一个工具包, 每一个工具包中都有各种不同的

工具供我们使用进而实现各种不同的功能.

模块就是一个Python文件,里面有类、函数、变量等,我们可以

拿过来用


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

[from 模块名] import [模块 | 类 | 变量 | 函数 | *]  [as 别名]

import 模块名
from 模块名 import 类、变量、方法等
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名

 案例:导入time模块

让程序睡眠了5秒钟


from 模块名 import 功能名

from 模块名 import 功能名

功能名()


案例:导入time模块中所有的方法

 

自定义模块并使用

 自定义一个test函数,在另外一个直接调用

 


导入多个模块的时候,且模块内有同名功能. 当调用这个同名功能的时候,调用到的是后面导入的模块的功能


if __main__ == “__main__”表示,只有当程序是直接执行的才会进入if内部,如果是被导入的,则if无法进入


__all__变量可以控制import *的时候哪些功能可以被导入 

Python 

Python的包定义:包就是一个文件夹,里面可以存放许多Python的模块(代码文件),通过包,在逻辑上将一批模块归为一类,方便使用。


__init__.py文件的作用?

创建包会默认自动创建的文件,通过这个文件来表示一个文件夹是Python的包,而非普通的文件夹

步骤如下:

① 新建包`my_package`

新建包内模块:`my_module1` `my_module2`

模块内代码如下


导入包

import 包名.模块名

包名.模块名.目标


 导入包方式二:

注意:必须在`__init__.py`文件中添加`__all__ = []`,控制允许导入的模块列表

第三方包 

第三方包的安装非常简单,我们只需要使用Python内置的pip程序即可。

打开:命令提示符程序,在里面输入:

pip install 包名称

即可通过网络快速安装第三方包


   Python基础综合案例
数据可视化 - 折线图可视化

   json数据格式  

JSON的定义: 是一种轻量级的数据交互格式。可以按照 JSON 指定的格式去组织和封装数据
JSON 本质上是一个带有特定格式的字符串

 主要功能json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互. 类似于:

l 国际通用语言 - 英语
l 中国 56 个民族不同地区的通用语言 - 普通话

各种编程语言 存储数据的容器 不尽相同 , Python 中有 字典 dict 这样的数据类型 , 而其它语言可能没有对应的字典。

为了让不同的语言都能够相互通用的互相传递数据,JSON就是一种非常良好的中转数据格式


json格式的数据要求很严格, 下面我们看一下他的要求 

# json数据的格式可以是:字典

{"name":"admin","age":18}

# 也可以是: 列表

[{"name":"admin","age":18},{"name":"root","age":16},{"name":"张三","age":20}]


准备列表,列表内每一个元素都是字典,将其转换为JSON


 准备字典,将字典转换为JSON


将JSON字符串转换为Python数据类型[{k: v, k: v}, {k: v, k: v}]


通过 json.dumps(data) 方法把python数据转化为了 json数据

data = json.dumps(data)

如果有中文可以带上:ensure_ascii=False参数来确保中文正常转换

通过 json.loads(data) 方法把josn数据转化为了 python列表或字典

data = json.loads(data)

pyecharts模块介绍 

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

pyechart网站:   pyecharts - A Python Echarts Plotting Library built with love. 

pyecharts-画廊:Document 

pyecharts入门 

l基础折线图

 


全局配置选项 

set_global_opts方法


全局配置选项的功能

配置图表的标题
配置图例
配置鼠标移动效果
配置工具栏
等整体配置项


通过json模块对数据进行处理数据处理

原始数据格式

导入模块: 

对数据进行整理, 让数据符合json格式: 

 


 


 l导入模块:

折线图相关配置项 置项配置项 

配置项           作用                          代码实例
init opts   对折线图初始化设置宽init_opts=opts.InitOpts(width="1600px",height="800px")
.add_xaxis添加x轴数据.add_xaxis(列表)
.add_yaxis   添加y轴数据

 创建折线图

 L = line(init_opts=opts.Initopts(width="1600px", height="800px"))

这里的Line()是构建类对象


添加数据 

  


.add_yaxis相关配置选项: 

配置项作用代码实例
series_name设置图例名称series_name="美国确诊人数"
y_axis设置y轴数据y_axis=["列表]
label_opts标签点的大小symbol_size=10
label_opts标签设置项:不显示标签label_opts=opts.LabelOpts(is_show=False)
linestyle_opts线条宽度和样式linestyle_opts=opts.LineStyleOpts(width=2)

.add_yaxis相关配置选项: 


 .set_global_opts全局配置选项: 

配置项作用代码实例
title_opts设置图表题和位置title_opts=opts.TitleOpts(title="标题",pos_left="center")
yaxis_optsy轴配置项yaxis_opts=opts.AxisOpts(name="累计确诊人数")
xaxis_optsx轴配置项xaxis_opts=opts.AxusOpts(name="时间")
legend_opts图例配置项legend.opts=opts.LgendOpts(pos_left=70%")

.set_global_opts(

  # 设置图标题和位置

  title_opts=opts.TitleOpts(title="2020年 印🇮🇳美🇺🇸日🇯🇵 累计确诊人数对比图",pos_left="center"),

  # x轴配置项

  xaxis_opts=opts.AxisOpts(name=时间),    # 轴标题

  # y轴配置项

  yaxis_opts=opts.AxisOpts(name=累计确诊人数),    # 轴标题

  # 图例配置项

  legend_opts=opts.LegendOpts(pos_left=‘70%‘),    # 图例的位置

)

 使用pyecharts构建基础的全国地图可视化图表

 


获取数据  

 

获取每个省份的确诊数据: 

 上述代码执行后输出,每个省的确诊数据:

创建地图并添加数据 

导入模块:

创建地图: 

添加数据: 

 

 添加数据

l设置全局配置选项 

 疫情地图-省级疫情地图

获取河南省各市数据

把各市数据汇总到一个列表中: 

参考国内疫情地图生成河南省疫情地图: 

基础柱状图

1. 通过Bar()构建一个柱状图对象

2. 和折线图一样,通过add_xaxis()add_yaxis()添加xy轴数据

3. 通过柱状图对象的:reversal_axis(),反转xy

4. 通过label_opts=LabelOpts(position="right")设置数值标签在右侧显示


通过Bar构建基础柱状图 


反转xy 


数值标签在右侧 

 

基础时间线柱状图 

 创建时间线

Timeline()-时间线 

BarLine对象是一张图表的话,时间线就是创建一个

一维的x轴,轴上每一个点就是一个图表对象


自动播放 


时间线设置主题 

 

 

 GDP动态柱状图绘制

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

参数 key ,是要求传入一个函数,表示将列表的每一个元素都传入函数中,返回排序的依据
参数 reverse ,是否反转排序结果, True 表示降序, False 表示升序

列表的sort方法 

带名函数形式                                                                                                             

 匿名lambda形式

 


处理数据

读取数据,删除第一条数据


将数据转换为字典存储,格式为:

{ 年份: [ [国家, gdp], [国家,gdp], ......  ], 年份: [ [国家, gdp], [国家,gdp], ......  ], ...... }      


准备时间线 


自动播放和绘图

理解使用对象完成数据组织的思路

使用对象组织数据

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

1. 在程序中设计表格,我们称之为:设计类(class

2. 在程序中打印生产表格,我们称之为:创建对象 

  

 3. 在程序中填写表格,我们称之为:对象属性赋值

 成员方法

类的使用语法

class 是关键字,表示要定义类了
类的属性,即定义在类中的变量(成员变量)

类的行为,即定义在类中的函数(成员方法


创建类对象的语法:

 


类的行为(方法)

 

可以看出,类中:

不仅可以定义属性用来记录数据
也可以定义函数,用来记录行为

 其中:

类中定义的属性(变量),我们称之为: 成员变量
类中定义的行为(函数),我们称之为: 成员方法

类中定义成员方法和定义函数基本一致,但仍有细微区别 

在方法定义的参数列表中,有一个:self关键字

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

它用来表示类对象自身的意思
当我们使用类对象调用方法的是, self 会自动被 python 传入
在方法内部,想要访问类的成员变量,必须使用 self


 self关键字,尽管在参数列表中,但是传参的时候可以忽略它

 在传入参数的时候,self是透明的,可以不用理会它

类和对象 

1.类和对象的关系是什么?

类是程序中的设计图纸

对象是基于图纸生产的具体实体


2. 什么是面向对象编程?

面向对象编程就是,使用对象进行编程。

即,设计类,基于类创建对象,并使用对象来完成具体的工作


构造方法 

使用构造方法向成员变量赋值 

在创建类对象(构造类)的时候, 会自动执行。
在创建类对象(构造类)的时候, 将传入参数自动传递给 __ init __ 方法使用。

 

 




构造方法名称:__init__   __init__   __init__ 千万不要忘记init前后都有2个下划线 

 •构造方法也是成员方法,不要忘记在参数列表中提供:self


  •在构造方法内定义成员变量,需要使用self关键字

 

 其它内置方法

__str__ 字符串方法 

 当类对象需要被转换为字符串之时,会输出如上结果(内存地址)

内存地址没有多大作用,我们可以通过__str__方法,控制类转换为字符串的行为。 

 




__lt__ 小于符号比较方法 

 

 




__le__ 小于等于比较符号方法 

方法名: __le__
传入参数: other ,另一个类对象
返回值: True False
内容:自行定义

>=符号实现的魔术方法是:__ge__

不过,实现了__le____ge__就没必要实现了




__eq__,比较运算符实现方法

方法名: __eq__
传入参数: other ,另一个类对象
返回值: True False
内容:自行定义

Ø 不实现 __eq__ 方法,对象之间可以比较,但是是比较内存地址,也即是:不同对象 == 比较一定是 False 结果。
Ø

实现了__eq__方法,就可以按照自己的想法来决定2个对象是否相等了




封装 

封装表示的是,将现实世界事物的:

属性
行为


封装到类中,描述为:

成员变量
成员方法


私有成员

既然现实事物有不公开的属性和行为,那么作为现实事物在程序中映射的类,也应该支持 

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

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


即可完成私有成员的设置定义私有成员的方式非常简单,只需要:

私有成员变量:变量名以 __ 开头( 2 个下划线)
私有成员方法:方法名以 __ 开头( 2 下划线)

 


私有方法无法直接被类对象使用                                

 私有变量无法赋值,也无法获取值

 


私有成员无法被类对象使用,但是可以被其它的成员使用。 

继承 

继承的引出 

继承分为:单继承和多继承

使用如图语法,可以完成类的单继承。

继承表示:将从父类那里继承(复制)来成员变量和成员方法(不含私有)


多继承注意事项 

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

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


pass关键字的作用是什么 

pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思 


复写和使用父类成员 

子类继承父类的成员属性和成员方法后,如果对其不满意,那么可以进行复写。

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

 


调用父类同名成员

一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员

如果需要使用被复写的父类的成员,需要特殊的调用方式:

方式1

调用父类成员

     使用成员变量:父类名.成员变量

     使用成员方法:父类名.成员方法(self)

方式2

使用 super() 调用父类成员

     使用成员变量:super().成员变量

     使用成员方法:super().成员方法()

 

只能在子类内调用父类的同名成员。

子类的类对象直接调用会调用子类复写的成员

 类型注解

函数(方法)的类型注解 

如图所示:

在编写函数(方法),使用形参 data 的时候,工具没有任何提示
在调用函数(方法),传入参数的时候,工具无法提示参数类型

这些都是因为,我们在定义函数(方法)的时候,没有给形参进行注解 

函数和方法的形参类型注解语法: 

 

 

 

 


函数(方法)的类型注解 - 返回值注解

同时,函数(方法)的返回值也是可以添加类型注解的。

语法如下:

 

 Union类型

1.使用Union可以定义联合类型注解 

2. Union的使用方式

导包: from typing import Union
使用: Union[ 类型 , ......, 类型 ]

多态 

多态指的是,同一个行为,使用不同的对象获得不同的状态。

如,定义函数(方法),通过类型注解声明需要父类对象,实际传入子类对象进行工作,从而获得不同的工作状态

 

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


多态常作用在继承关系上.

比如

函数 ( 方法 ) 形参声明接收父类对象
实际传入父类的子类对象进行工作

即:

以父类做定义声明
以子类做实际工作
用以获得同一行为, 不同状态


抽象类(接口)

父类Animalspeak方法,是空实现 

这种设计的含义是:

父类用来确定有哪些方法
具体的方法实现,由子类自行决定

这种写法,就叫做抽象类(也可以称之为接口)

抽象类:含有抽象方法的类称之为抽象类

抽象方法:方法体是空实现的(pass)称之为抽象方法


抽象类(接口)

抽象类就好比定义一个标准,

包含了一些抽象的方法,要求子类必须实现。

 

配合多态,完成

抽象的父类设计(设计标准)

具体的子类实现(实现标准) 

MySQL的安装      DBeaver (略)

    SQL基础与DDL(数据库定义)

SQL 语言,大小写不敏感
SQL 可以单行或多行书写,最后以 ; 号结束
SQL 支持注释:
单行注释: -- 注释内容( -- 后面一定要有一个空格)
单行注释: # 注释内容( # 后面可以不加空格,推荐加上)
多行注释: /*  注释内容   */


DDL - 库管理 

查看数据库(show databases;)

使用数据库(use 数据库名称;)

创建数据库(create database 数据库名称【charset utf8】;)

删除数据库(drop database 数据库名称;)

查看当前使用的数据库(select database();)


DDL - 表管理 

查看有哪些表:   show tables;   

删除表       drop table 表名称;

                 drop table if exist 表名称;

创建表:create table 表名称(

           列名称    列类型,

           列名称    列类型,

           。。。。。。

--------列类型有

int                            -------整数

float                          -------浮点数

varchar()                  -------文字,长度为数字,做最大长度限制

date                           -------日期类型

timestamp                -------时间戳类型

SQL - DML 

DML是指数据操作语言,英文全称是Data Manipulation Language,用来对数据库中表的数据记录进行更新 


数据插入 INSERT 

基础语法: insert into 表【(列1,列2,......, 列n)】values(值1,值2,......, 值n)[(值1, 值2,......, 值n), .......(值1,值2 ,......, 值n)]

注意:

1. 插入字符串数据,需要用单引号包围

2. 插入全部列的时候,列的列表可以省略


数据删除 DELETE 

基础语法:

delete from 表名称 【where 条件判断】

 

演示:


数据更新 UPDATE

基础语法

update 表名 set 列=值 【where 条件判断】;

 

演示:

SQL - DQL

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

基础语法:

 含义就是:

从(FROM)表中,选择(SELECT)某些列进行展示

演示: 


基础数据查询 - 过滤

查询也可以带有指定条件,语法如下: 

 

 演示:

 

DQLGROUP BY 进行分组聚合查询 

基础语法: 

select 字段 

演示

 SELECT中,除了聚合函数外,GROUP BY 了哪个列,哪个列在能出现在SELECT


对查询结果进行排序分页 

可以对查询的结果,使用ORDER BY 关键字,指定某个列进行排序,语法:

select 列 | 聚合函数 |* from 表

where ...

group by ...

order by ... [asc | desc]

演示: 


结果分页限制

同样,可以使用LIMIT关键字,对查询结果进行数量限制或分页显示,语法:

select 列|聚合函数|* from 表

where ...

group by ...

order by ... [asc | desc]

limit n [, m] 

 演示




 •WHEREGROUP BYORDER BY LIMIT均可按需求省略

SELECT FROM 是必写的
执行顺序:

FROM -> WHERE -> GROUP BY和聚合函数 -> SELECT -> ORDER BY -> LIMIT

Python执行SQL语句操作MySQL数据库软件 

pymysql 

除了使用图形化工具以外,我们也可以使用编程语言来执行SQL从而操作数据库。

Python中,使用第三方库:pymysql 来完成对MySQL数据库的操作 


创建到MySQL的数据库链接 




执行SQL语句 

演示,执行非查询性质的SQL语句 




执行查询性质的SQL语句:

游标对象使用 fetchall() 方法,得到的是全部的查询结果,是一个元组
这个元组内部嵌套了元组,嵌套的元组就是一行查询结果



如何获取链接对象?

from pymysql import Connection 导包
Connection( 主机 , 端口 , 账户 , 密码 ) 即可得到链接对象
链接对象 .close() 关闭和 MySQL 数据库的连接


如何执行SQL查询

通过连接对象调用cursor()方法,得到游标对象

游标对象 .execute() 执行 SQL 语句
游标对象 . fetchall () 得到全部的查询结果封装入元组内




Python执行SQL语句插入数据到MySQL 

commit提交 

如图所示代码,经过执行是无法将数据插入到数据表student中的。

这是为什么呢?

pymysql在执行数据插入或其它产生数据更改的SQL语句时,默认是需要提交更改的,即,需要通过代码确认这种更改行为。

通过链接对象.commit() 即可确认此行为。




自动commit 

可以在构建链接对象的时候,设置自动commit的属性。 

 Spark的介绍

 Apache Spark是用于大规模数据(large-scala data)处理的统一(unified)分析引擎。Spark是一款分布式的计算框架,用于调度成百上千的服务器集群,计算TBPB乃至EB级别的海量数据

SparkPython语言的支持,重点体现在,Python第三方库:PySpark之上。

PySpark是由Spark官方开发的Python语言第三方库。

Python开发者可以使用pip程序快速的安装PySpark并像其它三方库那样直接使用。

 PySpark库的安装

安装略


 构建PySpark执行环境入口对象 

想要使用PySpark库完成数据处理,首先需要构建一个执行环境入口对象。

PySpark的执行环境入口对象是:类 SparkContext 的类对象




PySpark的编程模型 

SparkContext类对象,是PySpark编程中一切功能的入口。

PySpark的编程,主要分为如下三大步骤:

 1.  数据输入(通过sparkcontext类对象的成员方法,完成数据的读取操作,读取后得到rdd类对象)

2. 数据处理计算(通过rdd类对象的成员方法,完成各种数据计算的需求)

3. 数据输出(将处理完成后的rdd对象,调用各种成员方法完成,写出文件,转换成list等操作)




数据输入:通过 SparkContext 完成数据读取
数据计算:读取到的数据转换为 RDD 对象,调用 RDD 的成员方法完成计算
数据输出:调用 RDD 的数据输出相关成员方法,将结果输出到 list 、元组、字典、文本文件、数据库等

  数据输入 

1.理解RDD对象 

PySpark支持多种数据的输入,在输入完成后,都会得到一个:RDD类的对象

RDD全称为:弹性分布式数据集(Resilient Distributed Datasets

PySpark针对数据的处理,都是以RDD对象作为载体,即:

数据存储在 RDD
各类数据的计算方法,也都是 RDD 的成员方法

RDD的数据计算方法,返回值依旧是RDD对象


PySpark的编程模型(下图)可以归纳为:

准备数据到 RDD -> RDD 迭代计算 -> RDD 导出为 list 、文本文件等
即:源数据 -> RDD -> 结果数据

 


Python数据容器转RDD对象 

PySpark支持通过SparkContext对象的parallelize成员方法,将:

list
tuple
set
dict
str

转换为PySparkRDD对象

 注意:

字符串会被拆分出 1 个个的字符,存入 RDD 对象
字典仅有 key 会被存入 RDD 对象




读取文件转RDD对象 

 PySpark也支持通过SparkContext入口对象,来读取文件,来构建出RDD对象

 




总结: 

1. RDD对象是什么?为什么要使用它?

RDD对象称之为分布式弹性数据集,是PySpark中数据计算的载体,它可以:

提供数据存储
提供数据计算的各类方法
数据计算的方法,返回值依旧是 RDD RDD 迭代计算)

后续对数据进行各类计算,都是基于RDD对象进行

2. 如何输入数据到Spark(即得到RDD对象)

通过 SparkContext 的parallelize成员方法,将 Python 数据容器转换为 RDD 对象
通过 SparkContext textFile 成员方法,读取文本文件得到 RDD 对象

   数据计算 

map方法:

PySpark的数据计算,都是依赖,RDD对象内置丰富的:成员方法(算子)

map 算子:功能是将RDD的数据一条条处理(处理的逻辑基于map算子中接收到的处理函数),返回新的RDD

语法:

map算子演示:

 对于传入参数的lambda表达式:

传入方法作为传参的时候,可以选择:

1. 定义方法,传入其方法名

2. 使用lambda,匿名方法的方式

如果方法体可以一行写完,用lambad方便,如果方法体复杂,就直接定义方法更方便 


总结:

1. map算子(成员方法)

接受一个处理函数,可用 lambda 表达式快速编写
RDD 内的元素逐个处理,并返回一个新的 RDD

2. 链式调用

对于返回值是新 RDD 的算子,可以通过链式调用的方式多次调用算子。


RDDflatMap方法 

 flatMap算子

功能: 对rdd执行map操作,然后进行接触嵌套操作

解除嵌套:

# 嵌套的list

list = 【【1,2,3】,【4,  5,6】,【7,8,9】】

 # 如果解除了嵌套

list = 【1,2,3,4,  5,6,7, 8, 9】

演示代码:




总结:

. flatMap算子

计算逻辑和 map 一样
可以比 map 多出,解除一层嵌套的功能

  RDDreduceByKey方法

接受一个处理函数,对数据进行两两计算 

功能:针对kv型rdd,自动按照key分组,然后根据你提供的聚合逻辑,完成 组内数据(value)的聚合操作。

用法:

rdd.reduceByKey(func)

# func : (v,v)

#接受2个传入参数(类型要一致),返回一个返回值,类型和传入要求一致


 reduceBeKey中的聚合逻辑是:

比如,有【1,2,3,4,5】,然后聚合函数是 :lambda a, b : a + b


RDDfilter方法 

 功能: 过滤想要的数据进行保留。

接受一个处理函数,可用 lambda 快速编写
函数对 RDD 数据逐个处理,得到 True 的保留至返回值的 RDD

RDDdistinct方法 

 distict 算子

功能:  对RDD数据进行去重,返回新RDD

语法:

rdd.disstinct()   无需传参

 RDDsortBy方法

 sortBY算子:

功能:  对RDD数据进行排序,基于指定的排序依据

 总结:

sortBy算子

接收一个处理函数, 可用 lambda 快速编写
函数表示用来决定排序的依据
可以控制升序或降序
全局排序需要设置分区数为 1

RDD的结果输出为Python对象的各类方法 

数据输入: sc.parallelize

                   sc.textFile

数据计算: rdd.map

                   rdd.flatMap

                   rdd.reduceByKey




collect 算子

功能:将RDD各个分区内的数据统一收集到Driver中, 形成一个list对象

用法:

rdd.collect()

返回值是一个list




reduce 算子

功能: 对RDD数据按照传入的逻辑进行聚合

语法:

代码 

 返回值等于计算函数的返回值




take算子

功能:取RDD的前N个元素,组合成list返回来




count算子

功能:计算RDD有多少条数据,返回值是一个数字


总结:

1. Spark的编程流程就是:

将数据加载为RDD(数据输入
对RDD进行计算(数据计算
RDD 转换为 Python 对象(数据输出)

2. 数据输出的方法

collect :将 RDD 内容转换为 list
reduce :对 RDD 内容进行自定义聚合
take :取出 RDD 的前 N 个元素组成 list
count :统计 RDD 元素个数

  RDD的内容输出到文件中 

1. RDD输出到文件的方法

rdd.saveAsTextFile ( 路径 )
输出的结果是一个文件夹
有几个分区就输出多少个结果文件

2. 如何修改RDD分区

SparkConf 对象设置conf.set("spark.default.parallelism", "1")
创建 RDD 的时候, sc.parallelize 方法传入 numSlices 参数为 1


高阶技巧     闭包

 

 

 

 

通过全局变量account_amount来记录余额

尽管功能实现是ok的,但是仍有问题:

代码在命名空间上(变量定义)不够干净、整洁
全局变量有被修改的风险

如何解决?

将变量定义在函数内部是行不通的
我们需要使用闭包



在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。  

 

 

 


简单闭包:

 


修改外部函数变量的值 

 

 


现在可以尝试实现以下atm取钱的闭包实现了

 

 

 

 


优点,使用闭包可以让我们得到:

无需定义全局变量即可实现通过函数,持续的访问、修改某个值
闭包使用的变量的所用于在函数内,难以被错误的调用修改

缺点:

由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存

 


总结:

1. 什么是闭包

定义双层嵌套函数, 内层函数可以访问外层函数的变量

将内存函数作为外层函数的返回,此内层函数就是闭包函数

2. 闭包的好处和缺点

优点:不定义全局变量,也可以让函数持续访问和修改一个外部变量
优点:闭包函数引用的外部变量,是外层函数的内部变量。作用域封闭难以被误操作修改
缺点:额外的内存占用

3. nonlocal关键字的作用

在闭包函数(内部函数中)想要修改外部函数的变量值

需要用nonlocal声明这个外部变量

 

  掌握装饰器的作用和用法

装饰器也是一种闭包, 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能 

 

 

希望给sleep函数,增加一个功能:

在调用 sleep 前输出:我要睡觉了
在调用 sleep 后输出:我起床了
可以用装饰器来实现

装饰器的一般写法(闭包写法) 

 

 

定义一个闭包函数, 在闭包函数内部:

执行目标函数
并完成功能的添加

 

 


装饰器的语法糖写法 

 

 

使用@outer

定义在目标函数sleep之上

 

 




总结:

1. 什么是装饰器

装饰器就是使用创建一个闭包函数,在闭包函数内调用目标函数。

可以达到不改动目标函数的同时,增加额外的功能。

2. 装饰器的写法 

 

设计模式  单例模式的作用和写法

设计模式是一种编程套路,可以极大的方便程序的开发。

最常见、最经典的设计模式,就是我们所学习的面向对象了。


单例模式 

 

创建类的实例后,就可以得到一个完整的、独立的类对象。

通过print语句可以看出,它们的内存地址是不相同的,即t1t2是完全独立的两个对象。

 

 

某些场景下, 我们需要一个类无论获取多少次类对象,都仅仅提供一个具体的实例

用以节省创建类对象的开销和内存开销

比如某些工具类,仅需要1个实例,即可在各处使用

这就是单例模式所要实现的效果。

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。

在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

定义: 保证一个类只有一个实例,并提供一个访问它的全局访问点

适用场景:当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时

单例的实现模式:

 

 

 


工厂模式的作用和写法 


 当需要大量创建一个类的实例的时候, 可以使用工厂模式。

即,从原生的使用类的构造去创建对象的形式

迁移到,基于工厂提供的方法去创建对象的形式

 

                    

 


使用工厂类的 get_person () 方法去创建具体的类对象

优点:

大批量创建对象的时候有统一的入口,易于代码维护
当发生修改,仅修改工厂类的创建方法即可
符合现实世界的模式,即由工厂来制作产品(对象)

 

 


多线程:进程、线程和并行执行 

 操作系统中可以运行多个进程,即多任务运行

一个进程内可以运行多个线程,即多线程运行


进程之间是内存隔离的, 即不同的进程拥有各自的内存空间。 这就类似于不同的公司拥有不同的办公场所。

线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间的。

这就好比,公司员工之间是共享公司的办公场所。

 

 

并行执行的意思指的是同一时间做不同的工作。

进程之间就是并行执行的,操作系统可以同时运行好多程序,这些程序都是在并行执行。

除了进程外,线程其实也是可以并行执行的。

也就是比如一个Python程序,其实是完全可以做到:

一个线程在输出:你好
一个线程在输出: Hello

像这样一个程序在同一时间做两件乃至多件不同的事情, 我们就称之为:多线程并行执行

 

多线程编程 

使用threading模块完成多线程编程 

 

 


 多线程编程

通过下方侧代码,即可实现多线程编程。

让一个Python程序实现启动2个线程,每个线程各自执行一个函数

 

 




 

 

 

需要传参的话可以通过:

args 参数通过元组(按参数顺序)的方式传参
或使用 kwargs 参数用字典的形式传参

 




总结:

1. threading模块的使用

thread_obj = threading.Thread(target=func创建线程对象

thread_obj.start() 启动线程执行

 

  

   Socket网络编程 

Socket

socket (简称 套接字) 是进程之间通信一个工具。


Socket客户端编程 

主要分为如下几个步骤: 

1. 创建socket对象

 

 2. 绑定socket_server到指定IP和地址

 

 3.  服务端开始监听端口

 

4.  接收客户端连接,获得连接对象 

 

 5. 客户端连接后,通过recv方法,接收客户端发送的消息

 

 6. 通过conn(客户端当次连接对象),调用send方法可以回复消息

 

 7. conn(客户端当次连接对象)和socket_server对象调用close方法,关闭连接

 

实现服务端并结合客户端进行测试

 

 

下载网络调试助手作为客户端

https://github.com/nicedayzhu/netAssist/releases

 

 


  基于Socket完成客户端程序开发

主要分为如下几个步骤: 

1. 创建socket对象 

 

 2. 连接到服务端

 

 3. 发送消息

 

4. 接收返回消息 

 

5. 关闭链接 

 

 




服务端客户端相互通讯

结合上一节学习的服务端代码,以及当前学习的客户端代码。

两者均运行起来,进行相互通讯 

 

 

 正则表达式

1. 什么是正则表达式

是一种字符串验证的规则,通过特殊的字符串组合来确立规则

用规则去匹配字符串是否满足

(^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$)可以表示为一个标准邮箱的格式

2. re模块的三个主要方法

re.match ,从头开始匹配,匹配第一个命中项
re.search ,全局匹配,匹配第一个命中项
re.findall ,全局匹配,匹配全部命中项

 

 正则表达式的各类元字符规则 

1.字符串的r标记表示,字符串内转移字符无效,作为普通字符使用 

2. 正则表达式的元字符规则 

 

 

 

 

 递归

1. 什么是递归

在满足条件的情况下,函数自己调用自己的一种特殊编程技巧

2. 递归需要注意什么?

注意退出的条件,否则容易变成无限递归
注意返回值的传递,确保从最内层,层层传递到最外层

3. os模块的3个方法

os.listdir ,列出指定目录下的内容
os.path.isdir ,判断给定路径是否是文件夹,是返回 True ,否返回 False
os.path.exists ,判断给定路径是否存在,存在返回 True ,否则返回 False

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值