Go第 10 章 :面向对象编程(上)

news2025/1/17 2:54:44

Go第 10 章 :面向对象编程(上)

10.1 结构体

10.1.1 看一个问题

请添加图片描述

10.1.2 使用现有技术解决

  1. 单独的定义变量解决
    代码演示:
    请添加图片描述
  2. 使用数组解决 代码演示:
    请添加图片描述

10.1.3 现有技术解决的缺点分析

  1. 使用变量或者数组来解决养猫的问题,不利于数据的管理和维护。因为名字,年龄,颜色都是属于一只猫,但是这里是分开保存。
  2. 如果我们希望对一只猫的属性(名字、年龄,颜色)进行操作(绑定方法), 也不好处理。
  3. 引出我们要讲解的技术-》结构体。

10.1.4 一个程序就是一个世界,有很多对象(变量)

请添加图片描述

10.1.5 Golang 语言面向对象编程说明

    1. Golang 也支持面向对象编程(OOP),但是和传统的面向对象编程有区别,并不是纯粹的面向对 象语言。所以我们说 Golang 支持面向对象编程特性是比较准确的。
    1. Golang 没有类(class),Go 语言的结构体(struct)和其它编程语言的类(class)有同等的地位,你可 以理解 Golang 是基于 struct 来实现 OOP 特性的。
    1. Golang 面向对象编程非常简洁,去掉了传统 OOP 语言的继承、方法重载、构造函数和析构函 数、隐藏的 this指针等等
    1. Golang 仍然有面向对象编程的继承,封装和多态的特性,只是实现的方式和其它 OOP 语言不 一样,比如继承 :Golang 没有 extends 关键字,继承是通过匿名字段来实现。
    1. Golang 面向对象(OOP)很优雅,OOP 本身就是语言类型系统(type system)的一部分,通过接口 (interface)关联,耦合性低,也非常灵活。后面同学们会充分体会到这个特点。也就是说在 Golang 中面 向接口编程是非常重要的特性。

10.1.6 结构体与结构体变量(实例/对象)的关系示意图

请添加图片描述
 对上图的说明

  1. 将一类事物的特性提取出来(比如猫类), 形成一个新的数据类型, 就是一个结构体。
  2. 通过这个结构体,我们可以创建多个变量(实例/对象)
  3. 事物可以猫类,也可以是 Person , Fish 或是某个工具类。。。

请添加图片描述

10.1.7 快速入门-面向对象的方式(struct)解决养猫问题

请添加图片描述

10.1.8 结构体和结构体变量(实例)的区别和联系

通过上面的案例和讲解我们可以看出:

  1. 结构体是自定义的数据类型,代表一类事物.
  2. 结构体变量(实例)是具体的,实际的,代表一个具体变量

10.1.9 结构体变量(实例)在内存的布局(重要!)

请添加图片描述

10.1.10 如何声明结构体

请添加图片描述
请添加图片描述

10.1.11 字段/属性

  • 基本介绍
  1. 从概念或叫法上看: 结构体字段 = 属性 = field (即授课中,统一叫字段)
  2. 字段是结构体的一个组成部分,一般是基本数据类型、数组,也可是引用类型。比如我们前面定义猫结构体 的 Name string 就是属性
  • 注意事项和细节说明
  1. 字段声明语法同变量,示例:字段名 字段类型
  2. 字段的类型可以为:基本类型、数组或引用类型
  3. 在创建一个结构体变量后,如果没有给字段赋值,都对应一个零值(默认值),规则同前面讲的一样:
    布尔类型是 false ,数值是 0 ,字符串是 “”。
    数组类型的默认值和它的元素类型相关,比如 score [3]int 则为[0, 0, 0]
    指针,slice,和 map 的零值都是 nil ,即还没有分配空间。
    案例演示:
    请添加图片描述
  4. 不同结构体变量的字段是独立,互不影响,一个结构体变量字段的更改,不影响另外一个, 结构体 是值类型。
    案例:
    请添加图片描述
    请添加图片描述
    请添加图片描述

10.1.12 创建结构体变量和访问结构体字段

  • 方式 1-直接声明
    案例演示: var person Person
    前面我们已经说了。

  • 方式 2-{}
    案例演示: var person Person = Person{}
    请添加图片描述

  • 方式 3-&
    案例: var person *Person = new (Person)

请添加图片描述

  • 方式 4-{}
    案例: var person *Person = &Person{}
    请添加图片描述

说明:

  1. 第 3 种和第 4 种方式返回的是 结构体指针。
  2. 结构体指针访问字段的标准方式应该是:(*结构体指针).字段名 ,比如 (*person).Name = “tom”
  3. 但 go 做了一个简化,也支持 结构体指针.字段名, 比如 person.Name = “tom”。更加符合程序员 使用的习惯,go 编译器底层 对 person.Name 做了转化 (*person).Name。

10.1.13 struct 类型的内存分配机制

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

10.1.14 结构体使用注意事项和细节

  1. 结构体的所有字段在内存中是连续的
    请添加图片描述
    请添加图片描述
    请添加图片描述
  2. 结构体是用户单独定义的类型,和其它类型进行转换时需要有完全相同的字段(名字、个数和类 型)
    请添加图片描述
  3. 结构体进行 type 重新定义(相当于取别名),Golang 认为是新的数据类型,但是相互间可以强转
    请添加图片描述
  4. struct 的每个字段上,可以写上一个 tag, 该 tag 可以通过反射机制获取,常见的使用场景就是序 列化和反序列化。
    请添加图片描述
    请添加图片描述

10.2 方法

10.2.1 基本介绍

在某些情况下,我们要需要声明(定义)方法。比如 Person 结构体:除了有一些字段外( 年龄,姓名…),Person 结构体还有一些行为比如:可以说话、跑步…,通过学习,还可以做算术题。这时就要用方法 才能完成。

Golang 中的方法是作用在指定的数据类型上的(即:和指定的数据类型绑定),因此自定义类型, 都可以有方法,而不仅仅是 struct。

10.2.2 方法的声明和调用

请添加图片描述
请添加图片描述
对上面的总结

  1. test 方法和 Person 类型绑定
  2. test 方法只能通过 Person 类型的变量来调用,而不能直接调用,也不能使用其它类型变量来调用
    请添加图片描述
  3. func (p Person) test() {}… p 表示哪个 Person 变量调用,这个 p 就是它的副本, 这点和函数传参非 常相似。
  4. p 这个名字,有程序员指定,不是固定, 比如修改成 person 也是可以
    请添加图片描述

10.2.3 方法快速入门

  1. 给 Person 结构体添加 speak 方法,输出 xxx 是一个好人
    请添加图片描述
  2. 给 Person 结构体添加 jisuan 方法,可以计算从 1+…+1000 的结果, 说明方法体内可以函数一样, 进行各种运算
    请添加图片描述
  3. 给 Person 结构体 jisuan2 方法,该方法可以接收一个数 n,计算从 1+…+n 的结果
    请添加图片描述
  4. 给 Person 结构体添加 getSum 方法,可以计算两个数的和,并返回结果
    请添加图片描述
  5. 方法的调用
    请添加图片描述

10.2.4 方法的调用和传参机制原理:(重要!)

 说明:
方法的调用和传参机制和函数基本一样,不一样的地方是方法调用时,会将调用方法的变量,当做 实参也传递给方法。下面我们举例说明。
 案例 1:
画出前面 getSum方法的执行过程+说明
请添加图片描述
说明:

  1. 在通过一个变量去调用方法时,其调用机制和函数一样
  2. 不一样的地方时,变量调用方法时,该变量本身也会作为一个参数传递到方法(如果变量是值类型,则进行值拷贝,如果变量是引用类型,则进行地址拷贝)

请添加图片描述
在方法栈中的对象 p是main 中的对象p的一个副本,是一个单独实例存在于getSum栈中
请添加图片描述

10.2.5 方法的声明(定义)

func (recevier type) methodName(参数列表) (返回值列表){
方法体
return 返回值
}

  1. 参数列表:表示方法输入
  2. recevier type : 表示这个方法和 type 这个类型进行绑定,或者说该方法作用于 type 类型
  3. receiver type : type 可以是结构体,也可以其它的自定义类型
  4. receiver : 就是 type 类型的一个变量(实例),比如 :Person 结构体 的一个变量(实例)
  5. 返回值列表:表示返回的值,可以多个
  6. 方法主体:表示为了实现某一功能代码块
  7. return 语句不是必须的。

10.2.6 方法的注意事项和细节

  1. 结构体类型是值类型,在方法调用中,遵守值类型的传递机制,是值拷贝传递方式
  2. 如程序员希望在方法中,修改结构体变量的值,可以通过结构体指针的方式来处理
    请添加图片描述
  3. Golang 中的方法作用在指定的数据类型上的(即:和指定的数据类型绑定),因此自定义类型, 都可以有方法,而不仅仅是 struct, 比如 int , float32 等都可以有方法
    请添加图片描述
  4. 方法的访问范围控制的规则,和函数一样。方法名首字母小写,只能在本包访问,方法首字母 大写,可以在本包和其它包访问。[讲解]
  5. 如果一个类型实现了 String()这个方法,那么 fmt.Println 默认会调用这个变量的 String()进行输出. 新版本的golang不可使用
    请添加图片描述

10.2.7 方法的课堂练习题

  1. 编写结构体(MethodUtils),编程一个方法,方法不需要参数,在方法中打印一个 10*8 的矩形,
    在 main方法中调用该方法。
type MethodUtils struct{
	//..
}

func (m MethodUtils) Print(){
	for i:=0;i<9;i++{
		for j:=0;j<7;j++{
			fmt.Print("*")
		}
		fmt.Println()
	}
}
func main() {
	//var i integer =10
	//i.print()
	//i.change()
	//fmt.Println("i=",i)
	//fmt.Println(i)
	var m MethodUtils
	m.Print()
}
  1. 编写一个方法,提供 m 和 n 两个参数,方法中打印一个 m*n 的矩形
    请添加图片描述
  2. 编写一个方法算该矩形的面积(可以接收长 len,和宽 width), 将其作为方法返回值。在 main 方法中调用该方法,接收返回的面积值并打印。
    请添加图片描述
  3. 编写方法:判断一个数是奇数还是偶数
    请添加图片描述
  4. 根据行、列、字符打印 对应行数和列数的字符,比如:行:3,列:2,字符*,则打印相应的效果
    请添加图片描述
  5. 定义小小计算器结构体(Calcuator),实现加减乘除四个功能
    实现形式 1:分四个方法完成:
    实现形式 2:用一个方法搞定
    请添加图片描述
type MethodUtils struct {
	Num1 float64
	Num2 float64
}
func (mu *MethodUtils) getRes(operator byte)float64{
	res := 0.0
	switch operator{
	case '+':
		res = mu.Num1 + mu.Num2
	case '-':
		res = mu.Num1 - mu.Num2
	case '*':
		res = mu.Num1 * mu.Num2
	case '/':
		res = mu.Num1 / mu.Num2
	default:
		fmt.Println("运算符输入错误")
	}
	return res
}


func main() {

	//m:=MethodUtils{1,2}
	//var m MethodUtils = MethodUtils{1,2}
	//var m *MethodUtils = new(MethodUtils)
	//(*m).Num2=1
	//(*m).Num1=2
	//m.Num2=3
	//m.Num1=4
	var m *MethodUtils = &MethodUtils{1,2}

	s := m.getRes('-')
	fmt.Println(s)
}

10.2.8 方法的课后练习题

请添加图片描述

package main

import "fmt"

type MethidUtils struct{
	num1 int
}

func (mu *MethidUtils)multiplication( ){
	for i:=1;i<=mu.num1;i++{
		for j:=1;j<=i;j++{
			fmt.Printf("%v*%v=%v \t",j,i,i*j)
			if i == j {
				fmt.Println()
			}
		}

	}
}

func main() {
	var m *MethidUtils
	fmt.Println("请输入乘法表")
	fmt.Scanln(&m.num1)

	m.multiplication()
}

请添加图片描述

package main

import "fmt"

//type MethidUtils struct {
//	num1 int
//}
type MethodUtils struct {
}

//func (mu *MethidUtils) multiplication() {
//	for i := 1; i <= mu.num1; i++ {
//		for j := 1; j <= i; j++ {
//			fmt.Printf("%v*%v=%v \t", j, i, i*j)
//			if i == j {
//				fmt.Println()
//			}
//		}
//
//	}
//}

func (mu *MethodUtils) exchange(array [3][3]int) {
	var array2 [3][3]int
	//遍历数组并进行转置
	for i := 0; i < len(array); i++ {
		for j := 0; j < len(array[i]); j++ {
			array2[j][i] = array[i][j]
		}
	}
	fmt.Println("转置后的矩阵为:")
	//遍历数组
	for i := 0; i < len(array2); i++ {
		for j := 0; j < len(array2[i]); j++ {
			fmt.Print(array2[i][j], " ")
		}
		fmt.Println()
	}
}

func main() {
	//var m *MethidUtils
	//fmt.Println("请输入乘法表")
	//fmt.Scanln(&m.num1)
	//
	//m.multiplication()

	var n *MethodUtils
	var arr = [3][3]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
	fmt.Println("转置前的矩阵为:")
	for i := 0; i < len(arr); i++ {
		for j := 0; j < len(arr[i]); j++ {
			fmt.Printf("%v ", arr[i][j])
		}
		fmt.Println()
	}
	n.exchange(arr)
}

10.2.9 方法和函数区别

  1. 调用方式不一样
    函数的调用方式: 函数名(实参列表)
    方法的调用方式: 变量.方法名(实参列表)

  2. 对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然
    请添加图片描述

  3. 对于方法(如 struct 的方法),接收者为值类型时,可以直接用指针类型的变量调用方法,反 过来同样也可以
    请添加图片描述
    请添加图片描述

总结:

  1. 不管调用形式如何,真正决定是值拷贝还是地址拷贝,看这个方法是和哪个类型绑定.
  2. 如果是和值类型,比如 (p Person) , 则是值拷贝, 如果和指针类型,比如是 (p *Person) 则是地址拷贝。

10.3 面向对象编程应用实例

10.3.1 步骤

  1. 声明(定义)结构体,确定结构体名
  2. 编写结构体的字段
  3. 编写结构体的方法

10.3.2 学生案例:

  1. 编写一个 Student 结构体,包含 name、gender、age、id、score 字段,分别为 string、string、int、 int、float64 类型。
  2. 结构体中声明一个 say 方法,返回 string 类型,方法返回信息中包含所有字段值。
  3. 在 main 方法中,创建 Student 结构体实例(变量),并访问 say 方法,并将调用结果打印输出。
  4. 走代码
package main

import "fmt"

type Student struct {
	name   string
	gender string
	age    int
	id     uint64
	score  float64
}

func (s *Student) say() string {
	var information string
	information = fmt.Sprintf("学生的姓名为%v,性别为%v,年龄为:%v,id号为:%v,分数为:%v", s.name, s.gender, s.age, s.id, s.score)
	return information
}

func main() {
	var student *Student = &Student{"tianyi", "男", 18, 8848, 100.0}
	//var student = Student{
	//	name:"tom",
	//	gender:"male",
	//	age : 18,
	//  id:8848,
	//	score:100.0,
	//}
	info := student.say()
	fmt.Println(info)
}


10.3.3 小狗案例 [学员课后练习]

  1. 编写一个 Dog 结构体,包含 name、age、weight 字段
  2. 结构体中声明一个 say 方法,返回 string 类型,方法返回信息中包含所有字段值。
  3. 在 main 方法中,创建 Dog 结构体实例(变量),并访问 say 方法,将调用结果打印输出

10.3.4 盒子案例

  1. 编程创建一个 Box 结构体,在其中声明三个字段表示一个立方体的长、宽和高,长宽高要从终 端获取
  2. 声明一个方法获取立方体的体积。
  3. 创建一个 Box 结构体变量,打印给定尺寸的立方体的体积
  4. 走代码
    请添加图片描述

10.3.5 景区门票案例

  1. 一个景区根据游人的年龄收取不同价格的门票,比如年龄大于 18,收费 20 元,其它情况门票免 费.
  2. 请编写 Visitor 结构体,根据年龄段决定能够购买的门票价格并输出
  3. 代码:
package main

import "fmt"

type Vistor struct {
	Name string
	Age int
}

func (v *Vistor) showPrice(){
	if v.Age >=90 ||v.Age<=8{
		fmt.Println("考虑到安全,别玩了")
		return
	}else if v.Age>18{
		fmt.Printf("游客的名字为%v 年龄为%v 收费20\n",v.Name,v.Age)
	}else{
		fmt.Printf("游客的名字为%v 年龄为%v free\n",v.Name,v.Age)
	}

}

func main() {
	var v Vistor
	for  {
		fmt.Println("请输入你的名字")
		fmt.Scanln(&v.Name)
		if v.Name=="n"{
			fmt.Println("退出程序")
			break
		}

		fmt.Println("请输入你的年龄")
		fmt.Scanln(&v.Age)
		v.showPrice()
	}
}

10.4 创建结构体变量时指定字段值

 说明
Golang 在创建结构体实例(变量)时,可以直接指定字段的值
 方式 1
请添加图片描述
 方式 2
请添加图片描述

10.5 工厂模式

10.5.1 说明

Golang 的结构体没有构造函数,通常可以使用工厂模式来解决这个问题

10.5.2 看一个需求

请添加图片描述
请添加图片描述
请添加图片描述

10.5.4 思考题

同学们思考一下,如果 model 包的 student 的结构体的字段 Score 改成 score,我们还能正常访问
吗?又应该如何解决这个问题呢?[老师给出思路,学员自己完成]

请添加图片描述
请添加图片描述

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

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

相关文章

AI与艺术——图像生成网络经典算法

生成模型是一种训练模型进行无监督学习的模型&#xff0c;即&#xff0c;给模型一组数据&#xff0c;希望从数据中学习到信息后的模型能够生成一组和训练集尽可能相近的数据。图像生成&#xff08;Image generation&#xff0c;IG&#xff09;则是指从现有数据集生成新的图像的…

代码块和执行顺序

1、什么是代码块 使用{}定义的一段代码我们称之为代码块 一般分为&#xff1a; 1. 普通代码块 2. 实例代码块 3. 静态代码块 2、普通代码块 定义在方法中的代码块&#xff0c;可以用于限定局部变量的生命周期。 public class Main{public static void main(String[] args) {{…

【分享】百度更喜欢自媒体站,9种方法让你轻松玩转微博营销

微博营销是指通过微博平台为商家、个人等创造价值而执行的一种营销方式。 以下九种方式&#xff0c;你一定要学习一下&#xff0c;视频最后&#xff0c;有干货。 1、注重价值的传递 企业博客经营者首先要改变观念——企业微博的“索取”与“给予”之分&#xff0c;企业微博是…

2023你冲不冲,冲冲冲冲~~

前言&#xff1a;\textcolor{Green}{前言&#xff1a;}前言&#xff1a; &#x1f49e;2022已经成为历史&#xff0c;趁着还没有遗忘来看看我这一年发生了什么事。 在这一年中有很多的收获也有一些遗憾&#xff0c;但是这不会让我停下来&#xff0c;未来的2023又会发生什么&…

ArcGIS 中的 7 种主要地理处理工具

地理处理工具可以提高人们的工作效率&#xff0c;并且这些工具可以批量应用于编辑&#xff0c;例如应用于所有功能或所有选定功能。本文将和大家一起探讨 7 个 ArcGIS 中的地理处理工具。 地理处理的用途 模型中的地理处理工具可解决许多空间完整性的问题&#xff0c;应用地理…

分布式缓存系统 Ignite、Hazelcast、Ehcache

一、Apache IgniteApache Ignite是一个以内存为中心的分布式数据库、缓存和处理平台&#xff0c;支持事务、分析以及流式负载&#xff0c;可以在PB级数据上享有内存级的性能。如果禁用原生持久化&#xff0c;Ignite就是一个分布式缓存&#xff0c;它实现了JCache规范&#xff0…

深入解析Linux虚拟化KVM-Qemu分析之中断虚拟化

说明&#xff1a; KVM版本&#xff1a;5.9.1QEMU版本&#xff1a;5.0.0工具&#xff1a;Source Insight 3.5&#xff0c; Visio 1. 概述 本文会将ARM GICv2中断虚拟化的总体框架和流程讲清楚&#xff0c;这个曾经困扰我好几天的问题在被捋清的那一刻&#xff0c;让我有点每有…

JsonUtility读写json简单应用

使用Unity提供的JsonUtility 简单封装了一个将数据以json格式存储到本地,方便数据读写的案例;一共三个脚本:MyJsonRW : 提供SaveJsonData和LoadWithJson,实现数据与json的转换和读写;TestData : 测试数据类,列举了部分常用的简单数据类型(不过有坑,后面会说);MyJsonExample : 例…

新诤信张强—兔年展望|2023-2025:看风的必不撒种、望云的必不收割

新诤信知识产权服务股份有限公司 首席技术官 张强 “看风的必不撒种、望云的必不收割”出自古老的犹太智慧书《传道书》&#xff0c;意思是&#xff0c;如果要等刮风才撒种&#xff0c;快要下雨才收割&#xff0c;一切就都来不及了。元宇宙的发展布局&#xff0c;也是这个道理…

基础算法[四]之图的那些事儿

文章目录前言图的表示邻接矩阵邻接表结构存储遍历路径搜索多源最短路问题问题描述Floyd实现模板单源最短路径问题Dijkstra算法朴素版本堆优化邻接表python实现Bellman-Ford 算法实现SPFA 算法实现python 版本判断负环小结最小生成树Prim算法Kruskra算法实现python版本二分图二分…

网络资源归档标准WARC介绍

WARC---Web ARChive 01 ● WARC格式概述 ● WARC&#xff08;Web ARChive&#xff09;格式是网络资源存档中使用的常见文件格式&#xff0c;全称为Web Archive File Format&#xff0c;由互联网保存联盟&#xff08;International Internet Preservation Consortium&#xff0…

2023年1月6日星期五-PPP/BPP相关学习

独立均匀分布matlab的rand指令可以帮助我们生成[0,1]的均匀分布的数据,这样,如果我们想要[a,b]的分布数据,只需要a+(b-a)*rand就可以了。 [a,b] 均值,标准差 均值

Git 常用基本命令

文章目录基本命令仓库相关命令提交相关命令分支相关命令tag 相关命令撤销相关命令IDEA Git 相关操作仓库相关操作提交相关操作提交代码步骤分支相关操作tag 相关操作撤销相关操作参考资料本文主要介绍 Git 常用的基本命令。基本命令 仓库相关命令 创建新仓库 git init克隆项…

C#,图像二值化(15)——全局阈值的一维最大熵(1D maxent)算法及源程序

1、最大熵&#xff08;maxent&#xff09; 最大熵&#xff08;maxent&#xff09;方法植根于信息理论&#xff0c;并已成功应用于许多领域&#xff0c;包括物理学和自然语言处理。它创建了一个模型&#xff0c;该模型最好地解释了可用数据&#xff0c;但有一个约束&#xff0c…

甘特图中的依赖关系是什么?

依赖关系是甘特图应用中常见的概念。甘特图依赖关系也称为任务依赖关系&#xff0c;它是指项目任务之间的关系&#xff0c;需要按特定顺序执行一个或多个任务才能完成某项任务&#xff0c;依赖于完成前一任务的任务是后继任务&#xff0c;而其依赖的任务是前导任务。依赖关系一…

字典特征提取、文本特征提取、jieba分词处理、tf-idf文本特征提取概念及代码实现

一、特征提取 特征提取&#xff1a;将任意数据&#xff08;如文本或图像&#xff09;转换为可用于机器学习的数字特征&#xff0c;特征值化是为了计算机更好的去理解数据 特征提取api&#xff1a;sklearn.feature_extraction 特征提取分类 字典特征提取(特征离散化)文本特征…

小蓝本 第一本《因式分解技巧》 第九章 待定系数法 笔记 (第九天)

小蓝本 第一本《因式分解技巧》 第九章 待定系数法 笔记 &#xff08;第九天&#xff09;前言待定系数法二次因式一次因式分解缺陷二次因式分解方法注意既约的情况拓展习题9题目题解前言 已经进行了9天&#xff0c;第八章有一点烧脑&#xff0c;但感觉还是很不错的&#xff0c…

Python类继承:深入了解

引言 前段时间刚好学习了&#xff0c;C中类方面的内容&#xff0c;发现和Python中有许多不同之处&#xff0c;尤其是在类的继承这一块&#xff0c;今天有空&#xff0c;正好写篇文章&#xff0c;记录一下有兴趣的东西&#xff0c;也算是对Python的一个复习。 1 C中的构造析构函…

设计模式学习(二):Observer观察者模式

一、什么是Observer模式在Observer模式中&#xff0c;当观察对象的状态发生变化时&#xff0c;会通知给观察者。Observer模式适用于根据对象状态进行相应处理的场景。简单一句话概况就是&#xff1a;观察者会发送观察对象状态变化的通知。二、Observer模式示例代码下面示例程序…

10种顶流聚类算法Python实现(附完整代码)

目录 前言 一、聚类 二、聚类算法 三、聚类算法示例 1、库安装 2、聚类数据集 3、亲和力传播 4、聚合聚类 5、BIRCH 6、DBSCAN 7、K均值 8、Mini-Batch K-均值 9、均值漂移聚类 10、OPTICS 11、光谱聚类 12、高斯混合模型 三、总结 前言 今天给大家分享一篇关…