Python语言进阶学习

news2024/11/27 1:24:38

目录

一、类、对象和成员方法

二、构造方法

三、面向对象

(1)封装

(2)继承

单继承

多继承

复写

super:调用父类同名成员

(3)多态 

(4)抽象类

五、Python操作MySQL数据库

六、闭包和装饰器

闭包概念

闭包作用

装饰器

装饰器一般写法

装饰器语法糖写法

七、设计模式:单例模式和工厂模式

单例模式

工厂模式

八、多线程编程

进程与线程

并发与并行

多线程编程:threading模块

传参方式 args\kwargs

九、网络编程

socket概念

socket服务端编程

socket客户端编程

十一、正则表达式

正则表达式

正则基础方法

正则元字符匹配


一、类、对象和成员方法

类是一组相关属性和行为的集合。

对象是类的实例,由于对象是根据类创建出来的,所以对象具备类中的属性和行为。

创建类语法:

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

创建类对象语法: (Java中创建对象语法是 类名称  对象名  =  new  类名称() ,Python与Java不同,牢记 )

对象名 = 类名称()

创建类成员方法语法:

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

注意点:1、写在类外面的函数叫做函数,而写在类里面的函数叫做方法

              2、在方法定义的参数列表中,self关键字是必须填写的

             3、self 用来表示类对象本身的意思

             4、当我们使用类对象调用方法的时候,self会自动被Python传入

             5、在方法内部,想要访问类的成员变量,必须使用self

             6、self 虽然出现在形参列表中,但在调用方法时无需理会,不需要传入该self参数

示例:创建一个Student类,属性有学生姓名和年龄,创建方法

二、构造方法

构造方法通常可以用来初始化对象,Java和Python 都使用构造方法来初始化对象的成员变量。

Python中类通过使用__init__()方法,称为构造方法。构造方法是一种特殊方法(init),以两个下划线开头,两个下划线结尾

构造方法可以实现:

  • 在创建对象的时候,构造方法会自动执行
  • 在创建对象的时候,构造方法会将传入参数自动传递给__init__()方法使用(两个下划线开头,两个下划线结尾)

三、面向对象

Python面向对象的特征包括封装、继承和多态。(Java语言也是面向对象,可参考Java)

   1.封装:根据职责将属性和方法封装到一个抽象的类中
   2.继承:实现代码的重用,相同的代码不需要重复的写
   3.多态:以封装和继承为前提,不同的子类对象调用相同的方法,产生不同的执行结果

(1)封装

  • 封装就是使用特殊的语法,对成员属性和成员方法进行包装,达到保护和隐藏的目的。
  • 被封装的成员(又叫做私有成员)主要是供类的内部使用,类对象无法使用。

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

私有成员包括私有成员变量私有成员方法。其中类对象无法访问私有成员。

定义私有成员方式:

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

封装案例分析:

(2)继承

Python 语言中一个类可以通过继承来使用另外一个类的方法和属性。这样做的好处是继承通用的方法和属性,使代码更加的简洁、明了。

Python中继承可以分为单继承多继承

注意点:Java中的继承只有单继承,没有多继承。Java不允许一个子类同时继承多个父类

单继承

一个类只能维承一个父类的方式。

语法格式:

class father(): # 父类
    pass
class sun(father): # 子类 继承父类
    pass

多继承

一个类去继承多个父类的方式 。

语法格式:

class father(): # 定义第一个父类
    pass
class mother(): # 定义第二个父类
    pass
class sun(father,mother): # 子类 继承多个父类
    pass

多继承注意事项:

一个子类继承多个父类,当子类调用成员方法或者成员属性时。此时若多个父类都具有共同的成员方法或者成员属性,那么输出内容以继承顺序(从左到右)为优先级。 

复写

子类继承父类的成员方法、成员属性之后,如果需要对继承的父类方法、属性进行修改的话,就可以直接进行重新修改。

super:调用父类同名成员

当子类对父类的方法和属性进行复写重新修改后,此时当子类对象调用成员的时候,就会调用复写后的新成员。

如果我们需要调用父类复写前的成员时,此时就需要使用super关键字来指示调用父类的成员。

注意点:方式一、方式二只可以在子类内部方法里面调用父类的同名成员,而且子类的对象调用默认是调用子类复写的

(3)多态 

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

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

多态 一般 是 通过 继承 和 方法重写 实现 , 多个子类 继承 同一个父类 。

代码示例:


class Animal:    # 创建 animal父类
    name = "Animal"
    age = 0

    def make_sound(self):
        print("动物发音")


class Dog(Animal):  # 创建 dog子类
    def make_sound(self):
        print("汪汪")


class Cat(Animal):  # 创建 cat子类
    def make_sound(self):
        print("喵喵")


# 创建对象,调用同一个方法 make_sound
animal = Animal()
animal.make_sound()

dog = Dog()
dog.make_sound()

cat = Cat()
cat.make_sound()

运行结果:

(4)抽象类

方法体为空 , 也就是 pass 的方法 , 称为 " 抽象方法 " 。有 " 抽象方法 " 的类 , 称为 抽象类 。

父类只定义抽象方法 , 没有具体实现 。

抽象类只定义有哪些方法,子类负责实现具体的方法逻辑。


五、Python操作MySQL数据库

复习总结见此视频链接:https://www.bilibili.com/video/BV1qW4y1a7fU?p=136&vd_source=1a462675092f937f148277eae6265dff

六、闭包和装饰器

闭包概念

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

闭包格式要求:

1、必须有一个双层内嵌函数。

2、内嵌函数必须引用外部函数的变量。(使用关键字nonlocal可以修改外部函数的变量

3、外部函数的返回值必须是内嵌函数。

闭包作用

        当我们定义一个函数时,此时需要使用到外部的全局变量时,可以使用global关键字来接收全局变量。但此时这个全局变量若被其他类导入就有可能有被修改的风险。

        因此为了保证全局变量不被其他类篡改,于是就使用闭包将这个全局变量定义在外部函数的参数列表中,形成一个嵌套函数。

以下代码为演示闭包操作存取款账户余额的案例:

方式一:使用global关键字来接收全局变量

因使用此种方法,全局变量容易有被修改的风险,于是将使用闭包的方法来实现以上存取款账户余额功能。

方式二:使用闭包方法来实现:使用关键字nonlocal可以修改外部函数的变量 (nonlocal使用在内部函数方法体中)

闭包的使用方法可以分为两种:内部函数中不需要修改外部函数的全局变量(简单闭包)、内部函数中需要修改外部函数的全局变量(复杂闭包)。

一、简单闭包

# 简单闭包:不需要修改外部函数的全局变量
def func(name):
    def func1(msg):
        print(f"{name}对我说:{msg}")
    return func1


fu = func("小红")
fu("早上好")

fu1 = func("小军")
fu1("你刚刚在干嘛?")

二、复杂闭包(带有参数,使用关键字nonlocal可以修改外部函数的变量

nonlocal使用方式:在内部函数方法体中使用

# 复杂闭包(带有参数,使用关键字nonlocal可以修改外部函数的变量)
def func(name):
    def func1(msg):
        nonlocal name
        name = "小猫"
        print(f"{name}对我说:{msg}")

    return func1


fu = func("小红")
fu("早上好")

fu1 = func("小军")
fu1("你刚刚在干嘛?")

闭包优缺点

优点:不用定义全局变量,也可以让函数持续的访问和修改一个外部变量。全局变量是外部函数的参数列表,其不容易被误操作修改。

缺点:内部函数需要使用外部函数的全局变量,因此需要占据额外的内存空间。

闭包使用场景

  • 装饰器:在不修改原有函数代码的情况下,增加额外的功能。
  • 回调函数:封装了状态的函数可以作为回调函数传递给某些操作。
  • 函数工厂:根据输入参数的不同返回不同行为的函数。

装饰器

装饰器的概念就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新的功能。

装饰器使用方法使用创建一个闭包函数,在闭包函数的内部函数里面来调用目标函数

案例:有一个睡觉sleep功能,现在需要在sleep功能前加一个功能:

  • 在调用sleep功能前输出:我要睡觉了
  • 在调用sleep功能后输出:我要起床了

装饰器一般写法

装饰器语法糖写法

装饰器语法糖使用格式:在目标函数的上方使用 @+修饰函数名 ,然后再 直接调用目标函数方法 即可。

七、设计模式:单例模式和工厂模式


设计模式是一种编程套路,可以极大的方便程序的开发,最常见、最经典的设计模式,就是我们所学习的面向对象了。
除了面向对象外,在编程中也有很多既定的套路可以方便开发,我们称之为设计模式

  • 单例模式工厂模式
  • 建造者、责任链、状态、备忘录、解释器、访问者、观察者、中介、模板、代理模式等模式

单例模式

工厂模式

工厂模式就是将对象的创建由使用原生类本身创建转换到由特定的工厂方法来创建。

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


工厂模式的优点:

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

八、多线程编程

进程与线程

进程:就是一个程序,运行在系统之上,那么便称之这个程序为一个运行进程,并分配进程D方便系统管理。

线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位

进程就好比一家公司,是操作系统对程序进行运行管理的单位
线程就好比公司的员工,进程可以有多个线程(员工),是进程实际的工作者

1、操作系统中可以运行多个进程,即多任务运行
2、一个进程内可以运行多个线程,即多线程运行

注意点:

  • 进程之间是内存隔离的,即不同的进程拥有各自的内存空间。这就类似于不同的公司拥有不同的办公场所
  • 线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间的。这就好比,公司员工之间是共享公司的办公场所。

并发与并行

并发:并发是指两个或多个事件在同一时间间隔发生

并行:并行是指两个或者多个事件在同一时间时刻发生

区别如下:

处理方式不同

1、并发:并发在一台处理器上“同时”处理多个任务。

2、并行:并行在多台处理器上同时处理多个任务。

物理方式不同

1、并发是逻辑上的同时发生

2、并行是物理上的同时发生

来个比喻:并发是一个人同时吃3个馒头,而并行是3个人同时吃3个馒头

关键区别

  1. 并发是指多个任务交替地执行,即多个任务按照时间片轮转的方式交替执行,它们共享同一个处理器
  2. 并行是指同时执行多个任务,每个任务有自己独立的处理器


1、多个进程同时在运行,即不同的程序同时运行,称之为多任务并行执行
2、一个进程内的多个线程同时在运行,称之为多线程并行执行

多线程编程:threading模块

演示代码:


"""多线程编程演示:交替执行打印111、222"""
import threading
import time

# 定义两个函数来执行打印111、222
def func1():
    while True:
        print("111")
        time.sleep(1)
def func2():
    while True:
        print("222")
        time.sleep(1)

func1_thread = threading.Thread(target=func1)   #  创建线程
func2_thread = threading.Thread(target=func2)   #  创建线程

func1_thread.start()     # 开启线程
func2_thread.start()

传参方式 args\kwargs

多线程编程中使用args或者kwargs来进程参数传递。

args是以元组的方式进行传参,kwargs是以字典的方式进行传参。

九、网络编程

网络编程就是使用Socket来进行服务端和客户端开发

socket概念

socket(简称 套接字)是进程之间通信一个工具,好比现实生活中的插座,所有的家用电器要想工作都是基于插座进行。
进程之间想要进行网络通信需要socket。
socket负责进程之间的网络数据传输,好比数据的搬运工。

socket服务端编程

代码如下:

import socket

# 创建Socket对象
socket_server = socket.socket()

# 绑定ip地址和端口(使用元组形式传参)
socket_server.bind(("localhost", 8888))

# 监听端口
socket_server.listen(1)  # listen 方法内接受一个整数传参数,表示接受的链接数量

# 等待客户端链接
conn, address = socket_server.accept()  # accept方法返回的是二元元组(链接对象, 客户端地址信息)
# 可以通过 变量1,变量2= socket_server.accept()的形式,直接接受二元元组内的两个元素
# accept()方法,是阻塞的方法,等待客户端的链接,如果没有链接,就卡在这一行不向下执行了

print(f"接收到了客户端的链接,客户端的信息是: {address}")  # 接受客户端信息,要使用客户端和服务端的本次链接对象,而非socket_server对象

while True:  # 使用循环可以进行无数次服务端与客户端通信
    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"))  # encode可以将字符用编码为字节数组对象

# 关闭链接
conn.close()
socket_server.close()

socket客户端编程

代码如下:

# 演示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"服务端回复的消息是: {recv_data.decode('UTF-8')}")
# 关闭链接
socket_client.close()

视频学习链接:https://www.bilibili.com/video/BV1qW4y1a7fU?p=160&vd_source=1a462675092f937f148277eae6265dff

十一、正则表达式

正则表达式

正则表达式,又称规则表达式,是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式(规则)的文本
简单来说,正则表达式就是使用字符串定义规则,并通过规则去验证字符串是否匹配。
比如说如果需要验证一个字符串是否是符合条件的电子邮箱地址,只需要配置好正则规则,即可匹配任意邮箱。
比如通过正则规则: (w-]+w-]+)@w-]+.w-]+)+$) 即可匹配一个字符串是否是标准邮箱格式

正则基础方法

Python正则表达式使用re模块并基于re模块中三个基础方法来做正则匹配,分别是: matchsearchfindall 三个基础方法

(1)re.match
从被匹配字符串开头进行匹配,匹配成功返回匹配对象(包含匹配的信息),若开头匹配不成功(即使后面部分可以匹配成功也直接返回空)则直接返回空。

找到第一个匹配字符串就直接返回符合下标 (左闭右开),后面就停止继续匹配了。

(2)re.search
搜索整个字符串找出匹配的,从前向后找到第一个后就停止,不会再继续向后匹配了。若整个字符串都没有匹配成功则返回空None

(3) re.findall
匹配整个字符串找出全部匹配项,找不到则返回空list:[]

总结如下:

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

正则元字符匹配

以下是正则表达式的字符匹配规则:

字符串前面带上r的标记,表示字符串中转义字符无效,就是普通字符的意思

代码如下示例:

import re

s1 = "python1245s fbuvna *&9-!? shic38097d"

# (1) 找出所有的数字字符:\d 匹配数字0-9
result1 = re.findall(r"\d", s1)   # 字符串前面带上r的标记,表示字符串中转义字符无效,就是普通字符的意思
print(result1)

# (2)找出所有的英文字符:[] 自定义匹配规则
result2 = re.findall(r"[a-zA-Z]", s1)
print(result2)

# (3)找出所有的特殊字符:\W 数字字母下划线除外都为特殊字符
result3 = re.findall(r"\W", s1)
print(result3)

# (4)匹配账号,只能由字母和数字组成,长度限制6到10位
s2 = "python13"
result4 = re.findall(r"^[a-zA-Z0-9]{6,10}$", s2)  # ^匹配字符串开头,$匹配字符串结尾,{6,10}匹配字符串长度
print(result4)  # 匹配成功

s3 = "@python13"
result5 = re.findall(r"^[a-zA-Z0-9]{6,10}$", s3)  # ^匹配字符串开头,$匹配字符串结尾,{6,10}匹配字符串长度
print(result5)  # 匹配失败


# (5)匹配QQ号,要求纯数字,长度为5-7,第一位不为0
s4 = "123456"
result6 = re.findall(r"^[1-9][0-9]{4,6}$", s4)  # 若需要判断整个字符串就需要加字符串开头^和字符串结尾$(判断子串就不需要加^、$)
print(result6)

s5 = "012345"
result7 = re.findall(r"^[1-9][0-9]{4,6}$", s5)
print(result7)

# (6)匹配邮箱地址,只允qq、163、gmail这三种邮箱地址
"""
邮箱格式如下:
abc.efg.daw@gq.com.cn.eu.qq.aa.cc
abc@gq.com
{内容),{内容),{内容),内容),{内容),内容).内容).[内容)@内容)(内容).{内容)
"""

s6 = "31245@qq.com"
result8 = re.match(r"^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+$", s6)  # match从头开始匹配第一个符合条件的
print(result8)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1796855.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Codeforces Round 951 (Div. 2) C、D(构造、线段树)

1979C - Earning on Bets 构造题:观察到k范围很小,首先考虑最终硬币总数可以是多少,我们可以先假设最终的硬币总数为所有k取值的最小公倍数,这样只需要满足每个结果添加1枚硬币即可赚到硬币。 // Problem: C. Earning on Bets //…

MacOS M系列芯片一键配置多个不同版本的JDK

第一步:下载JDK。 官网下载地址:Java Archive | Oracle 选择自己想要下载的版本,一般来说下载一个jdk8和一个jdk11就够用了。 M系列芯片选择这两个,第一个是压缩包,第二个是dmg可以安装的。 第二步:编辑…

9.1.1 简述目标检测领域中的单阶段模型和两阶段模型的性能差异及其原因

9.1目标检测 场景描述 目标检测(Object Detection)任务是计算机视觉中极为重要的基础问题,也是解决实例分割(Instance Segmentation)、场景理解(Scene Understanding)、目标跟踪(Ob…

【机器学习】Qwen1.5-14B-Chat大模型训练与推理实战

目录 一、引言 二、模型简介 2.1 Qwen1.5 模型概述 2.2 Qwen1.5 模型架构 三、训练与推理 3.1 Qwen1.5 模型训练 3.2 Qwen1.5 模型推理 四、总结 一、引言 Qwen是阿里巴巴集团Qwen团队的大语言模型和多模态大模型系列。现在,大语言模型已升级到Qwen1.5&…

Git使用总结(git使用,git实操,git命令和常用指令)

简介:Git是一款代码版本管理工具,可以记录每次提交的代码,防止代码丢失,可实现版本迭代,解决代码冲突,常用的远程Git仓库:Gitee(国内)、GitHub(国外&#xff…

全球AI新闻速递6.7

1.智谱 AI 宣布全模型矩阵降价,开源 GLM-4-9B 系列模型。 2.复旦大学计划在2024-2025新学年推出至少100门。 3.思科:启动 10 亿美元 AI 基金,投资AI初创公司。 4.OpenAI和谷歌DeepMind员工联名发声:高级AI风险巨大,…

Flutter开发效率提升1000%,Flutter Quick教程之对Widget进行删除,剪切,粘贴

一,删除操作 1,首先我们选中要删除的Widget。 2,在左边的侧边栏,点击删除按钮,即可完成对组件的删除操作。 二,剪切。剪切是相同的道理,都是先选中,再点击对应的按钮。 1&#xff…

UE4_环境_材质函数

学习笔记,不喜勿喷,欢迎指正,侵权立删! 1、建立材质函数Distance_Fun,勾选公开到库。 2、添加函数输入节点FunctionInput, 这个输入我们想作为混合材质属性BlendMaterialAttributes的alpha输入节点&#x…

钓鱼攻击的隐性经济

近年来,网络钓鱼形势发生了重大变化,涵盖了各种类型的攻击。许多公司已经开发了分类法来对不同的网络钓鱼攻击进行分类,类似于BlueVoyant 提出的分类法。该分类法概述了几种类型的网络钓鱼攻击,例如: 1. 电子邮件钓鱼…

一举高“粽“,考生请注意!AI监考来了...

📢📢📢📣📣📣 作者:IT邦德 中国DBA联盟(ACDU)成员,10余年DBA工作经验, Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主,全网粉丝10万 擅长主流Oracle、My…

什么是Swagger UI ,swagger ui 的authorization怎么获取?

什么是Swagger UI Swagger UI 是一个用于可视化和交互式地展示API文档的工具。它是Swagger(现称为OpenAPI)生态系统的一部分,旨在帮助开发者和API用户更好地理解、测试和调试API。 主要功能和作用 1. API文档自动生成: Swagge…

用户管理的小demo--过滤器filter

1、创建 CharEncodingFilter.java package com.by.filter; import javax.servlet.*; import java.io.IOException; public class CharEncodingFilter implements Filter {Overridepublic void init(FilterConfig filterConfig) throws ServletException {}Overridepublic void …

一个AI板卡电脑--香橙派 AIpro

本文算是一个开箱测评,主要评估它和一个电脑的距离。 香橙派官网:香橙派(Orange Pi)-Orange Pi官网-香橙派开发板,开源硬件,开源软件,开源芯片,电脑键盘香橙派(Orange Pi)是深圳市迅龙软件有限公司旗下开源产品品牌;香橙派&#x…

LabVIEW飞机发动机测试与故障诊断系统

LabVIEW飞机发动机测试与故障诊断系统 基于LabVIEW开发了一个飞机发动机测试与故障诊断系统,能够实时监测发动机的运行参数,进行数据采集与分析,并提供故障诊断功能。系统采用高精度传感器和数据采集硬件,适用于发动机的性能测试、…

Flink Sql:四种Join方式详解(基于flink1.15官方文档)

JOINs flink sql主要有四种连接方式,分别是Regular Joins、Interval Joins、Temporal Joins、lookup join 1、Regular Joins(常规连接 ) 这种连接方式和hive sql中的join是一样的,包括inner join,left join&#xff…

240508Scala笔记

240508Scala笔记 Scala概述: SCala是Java的拓展,在Java的基础上又拓展了一些语法,例如: 输出Hello World println("HelloWorld")System.out.println("Hello Scala from Java") 上面两段代码都可以输出内容. package chapter01 ​ /*object: 关键字,声明…

python_将二维列表转换成HTML格式_邮件相关

python_将二维列表转换成HTML_邮件相关 data[["理想","2"],["理想2","3"]]def list_to_html_table(data):"""将二维列表转换为HTML表格格式的字符串。参数:data -- 二维列表,表示表格的数据。返回:一个字符…

手机相册的排列方式探讨

不论你是不是程序员,你一定留意过一个问题:相册 App 基本都将图片裁剪成了居中的 1:1 正方形。那么手机相册 App,为什么要将图片切割成 1:1 正方形,然后以网格排列?是行业标准吗? 自适应图片宽度的图库&a…

在不受支持的 Mac 上安装 macOS Sonoma (OpenCore Legacy Patcher v1.5.0)

在不受支持的 Mac 上安装 macOS Sonoma (OpenCore Legacy Patcher v1.5.0) Install macOS on unsupported Macs 请访问原文链接:https://sysin.org/blog/install-macos-on-unsupported-mac/,查看最新版。原创作品,转载请保留出处。 作者主…

[AIGC] 详解Mockito - 简单易学的Java单元测试框架

在Java的世界中, 单元测试是一项非常重要的任务. Mockito作为一个强大灵活的mock框架,可以帮助我们有效的编写和管理我们的单元测试. 了解并掌握Mockito的使用对于提高我们的开发效率和保证我们的软件质量有着巨大的帮助. 文章目录 什么是Mockito?Mockito的核心API…