python-最后-高级技巧
文章目录
1.递归🎯
文章目录
思路:写一个函数,列出文件夹内的全部内容,如果是文件就收集到list
如果是文件夹,就递归调用自己,再次判断。
"""
演示Python递归操作
需求:通过递归,找出一个指定文件夹内的全部文件
"""
*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")) # *判断指定路径是否存在
**
*test_os()
def get_files_recursion_from_dir(path):
*"""
* 从指定文件路径中,通过递归获取文件并添加到 *list中,并返回list
* :param path: *要搜索的文件根路径**
* :return: 返回全部搜索到的文本文件 *list[]
* *"""
* print(f"当前遍历的文件路径是: {path}")
file_list = []
# *获取当前 路径列表全部内容(不包括路径,只包含当前的文件名,或文件夹名)
* path_list = os.listdir(path)
for curPath in path_list:
# *拼接路径
* curr_path_all = path + "/" + curPath
# *判断当前路径是否为文件,不是文件,**在递归前返回值
* if os.path.isdir(curr_path_all):
file_list += get_files_recursion_from_dir(curr_path_all)
else:
file_list.append(curr_path_all)
return file_list
1.什么是递归在满足条件的情况下,函数自己调用自己的一种特殊编程技巧
2.递归需要注意什么?
注意退出的条件,否则容易变成无限递归注意返回值的传递,确保从最内层,层层传递到最外层
3.os模块的8个方法
- os.
listdir(path)
,列出指定目录下的内容 - os.
path.isdir(path)
,判断给定路径是否是文件夹,是返回True,否返回False - os.
path.exists(path)
,判断给定路径是否存在,存在返回True,否则返回False - os.
getcwd()
, 获取当前工作目录的路径 - os.
chdir(path)
, 改变当前工作目录到指定的路径 - os.
mkdir(path)
, 创建一个新的目录 - os.
rmdir(path)
, 删除一个空的目录 - os.
system(command)
执行一个系统命令
注意: 若不指定 path ,则path的默认值为当前工作目录路径
2.socket服务端🎃
介绍:
- 2个进程之间通过Socket进行相互通讯,就必须有服务端和客户端
- Socket服务端:等待其它进程的连接、可接受发来的消息、可以回复消息
- Socket客户端:主动连接服务端、可以发送消息、可以接收回复
"""
演示Socket服务端开发
"""
import socket
socket_server = socket.socket() # 1.创建服务端对象
socket_server.bind(("localhost",8888)) # 2.绑定 客服端,端口好
socket_server.listen(1) # 3.监听端口
# 4.等待客户端连接
connet,address=socket_server.accept() # 解构出(连接对象,客户端地址信息)
# accept 是阻塞方法,等待客户端的链接,如果没有连接,就一直卡着
print(f"接收到了客户端的连接信息: {address}")
while True:
# 接收客户端消息,使用客户端和服务端的本次链接对象,而非soket_server对象
data: str = connet.recv(1024).decode('utf-8')
print(f"客户端发来的消息是: {data}")
msg = input("请输入你要和客户端回复的消息")
if msg == 'exit':
break
connet.send(msg.encode('utf-8'))
# 关闭连接
connet.close()
socket_server.close()
总结: Scoket服务端链接
主要分为如下几个步骤:
- 创建socket对象
- 绑定socket_server到指定IP和地址
- 服务端开始监听端口
- 接收客户端连接,获得连接对象
- 客户端连接后通过recv很爱,接受客户端发送的消息
- 通过conn(客户端当次连接对象),调用send方法可以回复消息
- conn(客户端当次连接对象)和socket_server对象调用close方法,关闭连接
3.socket客户端🧧
客户端主要分为几个步骤:
- 创建socket对象
- 连接到服务端
- 发送消息
- 接受返回的消息
- 关闭连接
"""
演示Socket客户端开发
"""
import socket
# 1.创建socket对象
socket_clinet = socket.socket()
# 2.连接到服务端
socket_clinet.connect(("localhost",8888))
while True:
# 3.发送消息
msg = input("请输入要给服务端发送的消息")
if msg == 'exit':
break
socket_clinet.send(msg.encode("utf-8")) # 3.1.给服务端发送消息前编码 utf-8
# 接受返回的消息
recv_data= socket_clinet.recv(1024) # 1024是缓冲区的大小,一般1024即可,同样是recv方法是阻塞的
print(f"服务端回复的消息是: {recv_data.decode('utf-8')}") # 4.接收服务端的消息需要解码 utf-8
# 5.关闭服务端
socket_clinet.close()
4.装饰器👒
什么是装饰器?
装饰器就是使用创建一个闭包函数,在闭包函数内调用目标函数。可以达到不改动目标函数的同时,增加额外的功能。
"""
演示装饰器的写法
"""
def outer(func):
def inner():
print("我要睡觉了")
func()
print("我要起床了")
return inner
@outer # 使用装饰器, 解释: @outer === outer(),把当前sleep函数作为outer的参数,进行调用
def sleep():
import random
import time
print("我在睡觉中....")
time.sleep(random.randint(1, 5))
# 未使用装饰器的调用
# fn = outer(sleep)
# fn()
# 使用装饰器的调用
sleep()
总结:
装饰器其实也是一种闭包, 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
5.多线程✨
绝大多数编程语言,都允许多线程编程,Pyhton也不例外。
Python的多线程可以通过threading模块来实现。
threading.Thread的参数
"""
演示多线程编程的使用
"""
import time
import threading
def sing(msg):
while True:
print(msg)
time.sleep(1)
def dancer(msg):
while True:
print(msg)
time.sleep(1)
if __name__ == '__main__':
# 创建线程
sing_thread = threading.Thread(target=sing,args=("我要唱歌,哈哈",),name='鸡哥哥')
dancer_thread = threading.Thread(target=dancer,kwargs={"msg":"我在跳舞哦,啦啦啦"})
# 启动线程
sing_thread.start()
dancer_thread.start()
threading模块的使用
- thread_obj = threading.Thread(target=func) 创建线程对象
- thread_obj.start() 启动线程执行
6.工厂模式🔨
什么是工厂模式?
将对象的创建由使用原生类本身创建转换到由特定的工厂方法来创建
好处?
- 大批量创建对象的时候,有统一的入口,易于代码维护
- 当发生修改,仅修改工厂类的创建方法即可
- 符合现实世界的模式,即由工厂来制作产品(对象)
"""
演示设计模式之工厂模式
"""
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')
7.单利模式💥
说明:单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。
在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
定义: 保证一个类只有一个实例,并提供一个访问它的全局访问点
适用场景:当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时。
# 在定义文件中: 一个存放实例的文件
class StrTools:
pass
str_tool = StrTools()
# 在使用文件中:
from test import str_tool
s1 = str_tool
s2 = str_tool
print(id(s1)) # id都相同:1807992704208
print(id(s2)) # 1807992704208
# 说明引用的是同一个实例
8.闭包💌
# 使用 闭包
def account_create(inital_amount=0):
def atm(num, deposit=True):
nonlocal inital_amount
if deposit:
inital_amount += num
print(f"存款: +{num}, 账户余额: {inital_amount}")
else:
inital_amount -= num
print(f"取款: -{num}, 账户余额: {inital_amount}")
return atm
atm = account_create()
atm(10) # 存款: +10, 账户余额: 10
atm(10) # 存款: +10, 账户余额: 20
atm(10) # 存款: +10, 账户余额: 30
atm(15,False) # 取款: -15, 账户余额: 15
总结:
1.闭包的好处和缺点
优点1:
不定义全局变量,也可以让函数持续访问和修改一个外部变量
优点2:闭包函数引用的外部变量,是外层函数的内部变量。作用域封闭难以被误操作修改
缺点:额外的内存占用
2.nonlocal关键字的作用
在闭包函数(内部函数中)想要修改 外部函数的变量值 需要用nonlocal声明这个外部变量
3.global关键字的作用
在函数内想要修改全局变量 需要用 global 变量名 .
9.正则❌
- 什么是正则表达式
- 是一种字符串验证的规则,通过特殊的字符串组合来确立规则用规则去匹配字符串是否满足
- 如
(^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$)
可以表示为一个标准邮箱的格式
- re模块的三个主要方法
- re.match,从头开始匹配,匹配第一个命中项
- re.search,全局匹配,匹配第一个命中项
- re.findall,全局匹配,匹配全部命中项
- 字符串的r标记,表示当前字符串是原始字符串,即内部的转义字符无效而是普通字符
9.1 单字符匹配
9.2 数量匹配
9.3 边界匹配
9.4分组匹配
10.spark库💦💦💦
- 什么是Spark、什么是PySpark
- Spark是Apache基金会旗下的顶级开源项目,用于对海量数据进行大规模分布式计算。
- PySpark是Spark的Python实现,是Spark为Python开发者提供的编程入口,用于以Python代码完成Spark任务的开发
- PySpark不仅可以作为Python第三方库使用,也可以将程序提交的Spark集群环境中,调度大规模集群进行执行。
- 为什么要学习PySpark?
- 大数据开发是Python众多就业方向中的明星赛道,薪资高岗位多,Spark(PySpark)又是大数据开发中的核心技术
- PySpark库的安装
- 在”CMD”命令提示符程序内,输入:
- pip install pyspark
- 或使用国内代理镜像网站(清华大学源)
- pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyspark
- 在”CMD”命令提示符程序内,输入:
# 一、数据输入:
# 1.1. sc.parallelize() # Python对象
# 1.2. sc.textFile() # 文件
# 二、数据计算:
# 2.1.map算子(成员方法) # 参数一类型 f:(T) -> U
"""
接受一个处理函数,可用lambda表达式快速编写
对RDD内的元素逐个处理,并返回一个新的RDD
"""
# f:(T) -> U
# f:(T) -> T
# 在第一个注解中,表示函数 f 接受一个参数类型为 T 的参数,并返回一个类型为 U 的结果。实际上这个注解可以理解为“f 是一个接受类型为 T 的参数并返回类型为 U 的函数”。
# 在第二个注解中,表示函数 f 接受一个参数类型为 T 的参数,并返回类型也是 T。实际上这个注解可以理解为“f 是一个接受类型为 T 的参数并返回类型也是 T 的函数”。
# 2.2.flatMap算子(成员方法) # 参数一类型 f: (T) -> Iterable[U]
"""功能:对RDD执行map操作,然后进行解除一层嵌套的功能"""
# 其中 T 表示传入函数的元素类型,也就是 RDD 中的元素类型;
# Iterable[U]: 表示返回的可迭代对象中的元素同一类型。如: [1,2,3]或['h','i']
# 2.3.reduceByKey算子(成员方法)
"""功能:针对kv型的RDD,自动按照key分组,然后根据你提供的聚合逻辑,完成组内数据(value)的聚合操作"""
# 注意; reduceByKey中接受的函数,只负责聚合,不理会分组
# 2.4.Filter算子(成员方法)
"""功能:过滤想要的数据进行保留"""
# 注意: 返回是True的数据被保留,False的数据被丢弃
# 2.5.distinct算子(成员方法)
"""功能:对RDD数据进行去重"""
# 注意:无需传参
# 2.6.sortBy算子(成员方法)
"""功能:对RDD数据进行排序,基于你指定的排序依据."""
# 参数1: func: T -> U : 告知按照RDD中的哪个数据进行排序,比如 lambda x:x[1]表示按照rdd中的第二列元素进行排序
# 参数2: ascending: True升序 False降序
# 参数3: numPartitions: 用多少分区排序
# 三、数据输出:
# 输出为 Python对象
# collect(): 将rdd数据转换为 list 输出
# reduce(): 将rdd数据进行自定义聚合
# take(): 将rdd数据的前n个元素组成list
# count(): 统计rdd数据的元素个数
# 输出到 文件中
# saveAsTextFile(): 将rdd的数据写入文本文件中,支持本地写出,hdfs等文件系统
# sc.saveAsTextFile(文件输出地址)
# 设置rdd输出的 分区数
# 方式一: SparkConf对象设置属性全局并行度为 1:
conf = SparkConf().setMaster("loca[*]").setAppName("test_spark").set("spark.default.parallelism","1")
# 方式二: 创建rdd的时候设置(parallielze方法传入numSlices参数为1)
rdd1 = sc.parallelize([1, 2, 3, 4, 5], numSlices=1)
rdd1 = sc.parallelize([1, 2, 3, 4, 5], 1)
- 如何安装PySpark库
- pip install pyspark
- 为什么要构建SparkContext对象作为执行入口
- PySpark的功能都是从SparkContext对象作为开始
- PySpark的编程模型是?
- 数据输入:通过SparkContext完成数据读取
- 数据计算:读取到的数据转换为RDD对象,调用RDD的成员方法完成计算
- 数据输出:调用RDD的数据输出相关成员方法,将结果输出到list、元组、字典、文本文件、数据库等
- RDD对象是什么?为什么要使用它?
- rdd对象称之为 分布式弹性数据集,是PySqark中数据计算的载体,它可以:
- 提供数据存储
- 提供数据计算的各类方法
- 数据计算的方法,返回值依旧是rdd(rdd迭代计算)
- 后续对数据进行各类计算,都是基于rdd对象进行
- rdd对象称之为 分布式弹性数据集,是PySqark中数据计算的载体,它可以:
- 如何输入数据到Spark(记得到rdd对象)
- 通过SparkContext的parallelize成员方法,将python数据容器转换为rdd对象
- 通过SparkContext的textFile成员方法,读取文本文件得的rdd对象
11.类型注解
1.单一注解
方式一:
基础语法: 变量: 类型
# 基础数据类型注解
var1: int = 10
var2: float = 3.1434343
var3: bool = True
var4: str = "nihaoa"
# 基础容器类型注解
my_list: list = [1,3,4]
my_tuple: tuple = (1,3,4)
my_set: set = {1,3,4}
my_dict: dict = {"name": "hi"}
my_str: str = "hi"
#容器类型详细注解
my_list: list[int] = [1,3,4]
my_tuple: tuple[str,int,bool] = ("nickname",3,True)
my_set: set[int] = {1,3,4}
my_dict: dict[str,int] = {"age": 18}
# 注意:
# 元组类型设置类型详细注解,需要将每一个元素都标记出来
# 字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value
# 类对象类型注解
class Person:
pass
per: Person = Person()
# 函数(方法)的类型注解 - 形参注解
def fucn1(data:list):
data. # 有list方法提示 data.
def fucn2(x:int, y: int):
return x + y
# 函数(方法)的类型注解 - 返回值注解
def 函数方法名(形参: 类型,...,形参: 类型) -> 返回值类型:
pass
def add(x: int,y: int) -> int:
return x + y
def func(data: list[int]) -> list[int]:
pass
方式二:
除了使用 变量: 类型, 这种语法做注解外,也可以在注释中
进行类型注解。语法:
class Person:
pass
var1 = random.randint(1, 10) # type: int
var2 = json.loads(data) # type: dict[str, int]
var3 = func() # type: Person
1.联合(Union)类型注解
使用 Union[类型,…,类型],可以定义联合类型注解
示例:
from typing import Union
my_list: list[Union(int,str)] = [1,3,"hell","god"]
my_dict: dict[str, Union[str,int]] = {"name": "李天王","age": 13}
def func(data: Union[int,str]) -> Union[int,str]:
pass
12.面向对象
一.封装
1.封装到类中,描述为:成员变量
,成员方法
2.私有成员: 私有变量
,私有方法
3.如何定义私有成员?
成员变量和成员方法的命名均以 __作为开头即可
4.私有成员的访问限制?
- `类对象`无法访问(和设置)私有成员
- 类中的其他成员可以访问私有成员
二.继承
2.1 单继承: class 类名(父类名
):
继承表示: 将从父类那里继承(复制)来成员变量和成员方法(不含私有)
2.2 多继承: class 类名(父类1, 父类2, … ,父类N):
注意
:多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。即:先继承的保留,后继承的被覆盖
2.3 pass关键字的作用是什么?
pass 是占位符,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思
2.4 复写
子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。
即:在子类中
重新定义同名的属性或方法即可。
注意: 一旦复写
父类成员,那么类对象调用成员的时候,就会调用复写后的新成员
2.4.1如果需要使用被复写的父类的成员,需要特殊的调用方式:
方式一:
使用成员变量: 父类名.成员变量
使用成员方法: 父类名.成员方法(self)
方法二:
使用super()调用父类成员
使用成员变量: super().成员变量
使用成员方法: super().成员方法()
注意: 只可以在子类内部调用父类的同名成员,子类的实体类对象调用默认是调用子类复写的
三.多态
多态,指的是:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。
应用场景: 多态常作用在继承关系上.
比如
- 函数(方法)形参声明接收父类对象
- 实际传入父类的子类对象进行工作
即:
- 以父类做定义声明
- 以子类做实际工作用
- 以获得同一行为, 不同状态
使用抽象类:
如下例子: 一台空调,有不同的功能,比如 制冷,制热左右摆风
…,
而且不同的厂家生产的标准不同,如耗电,
# 演示抽象类
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)
总结:
1.什么是多态?
多态指的是,同一个行为,使用不同的对象获得不同的状态.
如,定义函数(方法),通过类型注解声明需要父类对象,实际传入子类对象进行工作,从而获得不同的工作状态.
2.什么是抽象类(接口)
包含抽象方法的类,称之为抽象类。抽象方法是指:没有具体实现的方法(pass)称之为抽象方法
3.抽象类的作用:
多用于做顶层设计(设计标准),以便子类做具体实现
也是对子类的一种软性约束,要求子类必须复写(实现)弗雷德一些方法
并配合多态使用,获得不同的工作状态