当前位置: 首页 > news >正文

Rust语言学习

Rust语言学习

  • 通用编程概念
  • 所有权
    • 所有权
    • 引用和借用
    • slice
  • struct(结构体)
    • 定义并实例化一个结构体
    • 使用结构体
    • 方法语法
  • 枚举 enums
    • 定义枚举
    • match控制流运算符
    • if let 简单控制流
  • 使用包、Crate和模块管理不断增长的项目(模块系统)
    • 包和crate
    • 定义模块来控制作用域与私有性
    • 路径用于引用模块树中的项
    • 使用use关键字将名称引入作用域
    • 将模块分割进不同文件
  • 常用集合
    • vrctor<T>
    • 使用字符串存储utf-8编码的文本
    • 哈希map存储键值对
  • 错误处理
    • panic!与不可恢复的错误
    • Rusult 与可恢复的错误
  • 泛型、trait、生命周期
    • 泛型数据类型
    • trait :定义共享的行为
    • 生命周期和引用有效性
  • 测试
    • 编写测试

通用编程概念

  1. let定义一个不可变的值,需要可变则 加mut;
  2. 使用const 声明常量,常量不仅是不可变的,它们始终是不可变的。常量只能设置为常量表达式,而不能设置为函数调用的结果或只能在运行时计算的任何其他值。
  3. 遮蔽,使用let对关键字进行阴影处理,例如let x = 5; let x = x + 1 ;
  4. 静态类型,Rust是一种静态类型的语言,必须在编译器知道所有变量的类型;
  5. 标量类型:整数、浮点数、布尔值、字符
  6. 复合类型:元组、数组
  7. 元组: 将多种类型的多个值组合为一个复合类型的一般方法。元组的长度是固定的:声明后,它们就无法增长或缩小。例如:let tup = (500, 6.4, 1); let (x, y, z) = tup;
  8. 数组:数组具有固定长度,例如:let a = [1, 2, 3, 4, 5]; let a: [i32; 5] = [1, 2, 3, 4, 5];
  9. 函数:蛇形大小写作为函数和变量名的常规样式。在蛇形情况下,所有字母均为小写,并在下划线之间使用单独的单词。
  10. 功能实体包含语句和表达式
  11. 语句:语句不返回值;如:let a= 5;
  12. 表达式:**{ let x=3; x+1 }**表达式不包括结尾分号。如果在表达式的末尾添加分号,则将其变成一条语句,然后该语句将不返回值。
  13. 具有返回值的函数:函数的返回值与函数主体块中最终表达式的值同义。您可以通过使用return关键字并指定一个值从函数中提前返回,但是大多数函数隐式返回最后一个表达式。例如:fn five() -> i32 { 5 }
  14. if bool { } else if bool {} else {}:if的条件不加() ,结果可赋值给变量
  15. 循环重复 :loop、while、for
  16. loop { // 逻辑 } :Rust提供了另一种更可靠的突破循环的方法。您可以将break关键字放在循环中,以告知程序何时停止执行循环;
let mut counter = 0;let result = loop {counter += 1;if counter == 10 {break counter * 2;}};
  1. while bool表达式 {}
```javascriptlet mut a = 0;let aa = [1,2,2,3,4];while a<aa.len() {println!("{}",aa[a]);a = a+2;}
```

所有权

所有权

  1. 所有权规则
    1. Rust中的每个值都有一个称为其所有者的变量。
    2. 值在任一时刻有且只有一个所有者。
    3. 当所有者(变量)离开作用域,该值将被删除。
  2. 所有权的存在为了管理堆数据
  3. String 类型存储在堆上,当离开作用域时,Rust会调用一个特殊函数,这个函数叫drop 放置释放内存的代码。
  4. Rust 永远也不会自动创建数据据的“深拷贝”,
  5. 变量与数据的交互方式:
    1. 移动 let s1 = s2; (主要是存储在堆里的数据,如果作为参数传入到新的函数中,之后不可使用,参考其下代码二)
    2. 克隆 clone()
  6. 只在栈上的拷贝 (区分上述的移动和拷贝)。Rust 有一个叫做 Copy trait 的特殊注解,。如果一个类型拥有 Copy trait,一个旧的变量在将其赋值给其他变量后仍然可用。
    1. 所有整数类型,比如 u32。
    2. 布尔类型,bool,它的值是 true 和 false。
    3. 所有浮点数类型,比如 f64。
    4. 字符类型,char。
    5. 元组,当且仅当其包含的类型也都是 Copy 的时候。比如,(i32, i32) 是 Copy 的,但 (i32, String) 就不是。
  7. 返回值也可以转移所有权
  8. 转移返回值的所有权(变量的所有权总是遵循相同的模式:将值赋给另一个变量时移动它。当持有堆中数据值的变量离开作用域时,其值将通过 drop 被清理掉,除非数据被移动为另一个变量所有。)
  9. 返回参数的所有权 (引用)
//代码二
fn main() {//s值移入到函数中 之后不在有效let s = String ::from("hello");takes_ownership(s);//返回值转移所有权let s2 = String::from("abc");let s3 = takes_and_give_back(s2);println!("s3:{}",s3);//转移返回值的所有权let s1 = String::from("word");let (s2, len) = calculate_length(s1);println!("s2:The length of '{}' is {}.", s2, len);let x =5; //x是copy的,所以后面可继续使用makes_copy(x);
}
fn takes_ownership(some_string:String){println!("{}",some_string);
}
fn makes_copy(some_integer:i32){println!("{}",some_integer);
}
fn takes_and_give_back(str:String) -> String {str
}
fn calculate_length(s: String) -> (String, usize) {let length = s.len(); // len() 返回字符串的长度(s, length)
}

引用和借用

  1. 引用就是符号&。 允许使用所有权但不获取所有权。
  2. 我们将获取引用作为函数参数称为借用。
  3. 正如变量默认是不可变的,引用也一样。(默认)不允许修改引用的值。
  4. 可变引用:&mut
  5. 在特定作用域中的特定数据中只能有一个可变引用,好处是可以在编译时就避免数据竞争,可以通过大括号创建一个新的作用域,以允许拥有多个可变引用,只是不能同时拥有。
  6. 引用的规则:在任意给定时间,要么只能有一个可变引用,要么只能有多个不可变引用。 引用必须总是有效的

slice

  1. 允许引用集合中一段连续的元素序列,而不引用整个集合。
  2. 没有所有权的数据类型
  3. 引用 &string[1…2] ; &string[…1]; &string[1…];(部分 或起止末尾的引用)。
  4. 所有权、借用和slice让rust在编译时确保内存安全。

struct(结构体)

自定义数据类型,允许命名和包装多个相关的值,形成一个有意义的组合。

定义并实例化一个结构体

  1. 变量与字段同名的字段初始化简写语法。
  2. 可使用结构体更新语法从其他实例创建实例。
  3. (元组结构体):使用没有命名字段的元组结构体来创建不同的类型。
  4. (类单元结构体):没有任何字段的结构体(因为它们类似于 (),即unit 类型。类单元结构体常常在你想要在某个类型上实现 trait 但不需要在类型中存储数据的时候发挥作用)。
  5. 结构体数据的所有权,(如果结构体存储被其对象拥有数据的引用,需要用上生命周期(lifetimes))

使用结构体

  1. {} 中加入 :? 指示符告诉 println! 我们想要使用叫做 Debug 的输出格式。Debug 是一个 trait,它允许我们以一种对开发者有帮助的方式打印结构体,以便当我们调试代码时能看到它的值。(参考代码如下)
  2. #[derive(Debug)] 注解
    let user = User {user_name: String::from("yyn"),age: 18,live: true};println!("user:{:#?}",user);#[derive(Debug)]
struct User{user_name:String,age:u16,live:bool,
}

方法语法

  1. 方法和函数类型 使用fn关键字,可以拥有参数和返回值 ,不同点:在结构体的上下文中被定义(或枚举或trait对象的上下文),并且第一个参数总是self,代表调用该方法的结构体实例。
  2. 自动引用和解引用: 方法调用时rust中少数几个拥有这种行为的地方:当使用 object.something() 调用方法时,Rust 会自动为 object 添加 &、&mut 或 * 以便使 object 与方法签名匹配。
  3. 方法有一个明确的接收者———— self 的类型。在给出接收者和方法名的前提下,Rust 可以明确地计算出方法是仅仅读取(&self),做出修改(&mut self)或者是获取所有权(self)。事实上,Rust 对方法接收者的隐式借用让所有权在实践中更友好。
  4. 关联函数(不以self作为参数的函数):impl的另一个有用的功能,它们与结构体相关联,他们仍然是函数,而不是方法,因为它们并不作用于一个结构体的实例,例如:String::from
  5. 每个结构体都允许拥有多个impl块。
  6. 结构体不是创建自定义类型的唯一方法,还有枚举。
fn main(){let mut r = Rectangle{width:20,height:20};r.setHeight(300);println!("r.area:{}",r.area());let square = Rectangle::square(300);println!("square:{}",square.height);
}#[derive(Debug)]
struct Rectangle {width:u32,height:u32,
}impl Rectangle{fn square(size:u32)-> Rectangle{return  Rectangle{ width:size,height:size};}fn setHeight(&mut self,height:u32){self.height = height;}fn area(&self) -> u32{self.height* self.width}
}

枚举 enums

定义枚举

  1. 可以将任意类型的数据放入到枚举成员中。例如:字符串、数字类型、或者结构体,还可以是另一个枚举。
  2. 结构体和枚举还有另一个相似点:使用impl来为结构体定义方法那样,也可以在枚举上定义方法
  3. Option枚举:为了拥有一个可能为空的值,你必须要显式的将其放入对应类型的 Option 中。接着,当使用这个值时,必须明确的处理值为空的情况。只要一个值不是 Option 类型,你就 可以 安全的认定它的值不为空。这是 Rust 的一个经过深思熟虑的设计决策,来限制空值的泛滥以增加 Rust 代码的安全性。
  4. match 表达式就是这么一个处理枚举的控制流结构:它会根据枚举的成员运行不同的代码,这些代码可以使用匹配到的值中的数据。

match控制流运算符

  1. 允许我们将一个值与一系列的模式相比较,并根据相匹配的模式执行相应代码。
  2. ** _ 通配符** :会匹配所有的值,通过将其放在其他分支之后,_将会匹配所有之前没有指定的可能的值。
  3. match 在只关心 一个 情况的场景中可能就有点啰嗦了。为此 Rust 提供了if let

if let 简单控制流

  1. if let 获取通过等号分隔一个模式和一个表达式,失去match强制要求的穷尽性检查。
  2. if let 包含一个else 。else块中代码与match表达式中的_分支块中的代码相同。

#[derive(Debug)]
enum IpAddKind{V4,V6(String)
}
#[derive(Debug)]
struct IpAddr{kind :IpAddKind,address:String,
}fn main(){//使用结构体和枚举定义数据let home = IpAddr{kind:IpAddKind::V4,address:String::from("127.0.0.1")};let loopback = IpAddr{kind:IpAddKind::V6(String::from("::1")),address:String::from("::1")};//使用matchlet b = value_in_ip_add_kind(home.kind);println!("v4:{}",b);let a = value_in_ip_add_kind(loopback.kind);println!("v6:{}",a);//Option<T>//let five = Some(5);//let six = plus_one(five);//let none = plus_one(None);//if let 使用let some_and_value = Some(4);if let Some(3) = some_and_value{println!("three");} else {println!("qita");}
}fn value_in_ip_add_kind(ip_add_kind:IpAddKind) -> u8 {match ip_add_kind{IpAddKind::V4 => 1,IpAddKind::V6(str)=>{println!("str:{}",str);return 2},}
}
fn plus_one(x:Option<i32>) -> Option<i32>{match x {None => None,Some(i) => Some(i+1)}
}

使用包、Crate和模块管理不断增长的项目(模块系统)

一个包可以包含多个二进制crate项和一个可选的crate库。伴随着包的增长,你可以将包中的部分代码提取出来做成独立的crate,这些crate则作为外部依赖项。
作用域
模块系统:
1、包(Packages): Cargo 的一个功能,它允许你构建、测试和分享 crate。
2、Crates :一个模块的树形结构,它形成了库或二进制项目。
3、模块(Modules)和 use: 允许你控制作用域和路径的私有性。
4、路径(path):一个命名例如结构体、函数或模块等项的方式
cargo new --lib 模块名
Rust 提供了将包分成多个 crate,将 crate 分成模块,以及通过指定绝对或相对路径从一个模块引用另一个模块中定义的项的方式。你可以通过使用 use 语句将路径引入作用域,这样在多次使用时可以使用更短的路径。模块定义的代码默认是私有的,不过可以选择增加 pub 关键字使其定义变为公有。

包和crate

  1. Cargo 遵循的一个约定:src/main.rs 就是一个与包同名的二进制 crate 的 crate 根。Cargo 知道如果包目录中包含 src/lib.rs,则包带有与其同名的库 crate,且 src/lib.rs 是 crate 根。Cargo提供了工作区间这一功能。
  2. crate 是一个二进制项或者库。crate root 是一个源文件,Rust 编译器以它为起始点,并构成你的 crate 的根模块.
  3. 包(package) 是提供一系列功能的一个或者多个 crate。一个包会包含有一个 Cargo.toml 文件,阐述如何去构建这些 crate。
  4. 包中所包含的内容由几条规则来确立。一个包中至多 只能 包含一个库 crate(library crate);包中可以包含任意多个二进制 crate(binary crate);包中至少包含一个 crate,无论是库的还是二进制的
  5. 如果一个包同时含有 src/main.rs 和 src/lib.rs,则它有两个 crate:一个库(main)和一个二进制项,且名字都与包相同。通过将文件放在 src/bin 目录下,一个包可以拥有多个二进制 crate:每个 src/bin 下的文件都会被编译成一个独立的二进制 crate
  6. cargo new name创建一个可执行工程 src/main.rs
  7. cargo new --lib name 创建一个库工程 src/lib.rs

定义模块来控制作用域与私有性

  1. paths(允许你命名项的路径);use(将路径引入作用域);pub(使项变为公有);as,外部包,glob运算符
  2. 模块让我们可以将一个 crate 中的代码进行分组,以提高可读性与重用性。模块还可以控制项的 私有性,即项是可以被外部代码使用的(public),还是作为一个内部实现的内容,不能被外部代码使用(private)。
  3. ** 定义一个模块**:是以 mod 关键字为起始,然后指定模块的名字,并且用花括号包围模块的主体。在模块内,我们还可以定义其他的模块。模块还可以保存一些定义的其他项,比如结构体、枚举、常量、特性、或者函数。

路径用于引用模块树中的项

  1. 路径分为绝对路径和相对路径:绝对路径(absolute path)从 crate 根开始,以 crate 名或者字面值 crate 开头。相对路径(relative path)从当前模块开始,以 self、super 或当前模块的标识符开头。
  2. 绝对路径和相对路径都后跟一个或多个由双冒号(::)分割的标识符。
  3. 模块还定义了Rust的私有性边界,Rust默认所有项都是私有的,父模块中的项不能使用子模块中的私有项,但是子模块中的项可以使用父模块中的项。
  4. 使用pub关键字创建公共项,使子模块的内部部分暴露给上级模块。
  5. 使用super起始的相对路径。
  6. 使用pub 可以设计公有的结构体和枚举,我们还可以决定每个结构体的字段是否公有。
  7. 如果结构体中具有私有字段,我们需要提供公共的关联函数来构造结构体的实例。
  8. 与结构体相反**,如果把枚举设置为公有,它的成员都将变为公有。**

使用use关键字将名称引入作用域

  1. 使用use关键字将路径一次性引入作用域,然后调用该路径的项。
  2. 使用use 将两个同名类型引入同一个作用域这个问题还有另一个解决办法 使用as关键字指定一个新的本地名或者别名。 例如:use std::fmt::Result; use std::io::Result as IoResult;
  3. 使用 pub use 重导出名称,将项引入作用域,并同时使其可供其他代码引入自己的作用域。
  4. 使用外部包 Cargo.toml 加入 [dependence] rand=“0.5.5” ,加入一行use起始的包名。
  5. crates.io 上有很多 Rust 社区成员发布的包,将其引入你自己的项目都需要一道相同的步骤:在 Cargo.toml 列出它们并通过 use 将其中定义的项引入项目包的作用域中。 例如:[dependencies] rand = “0.5.5”
  6. 嵌套路径来消除大量的use行。 例如:use std::{cmp::Ordering,io}
  7. 通过glob运算符将所有的公有定义引入作用域 ** *,glob运算符 **,glob运算符经常用于测试模块tests中,后面讲解。

将模块分割进不同文件

  1. mod *** 后使用分号,而不是代码块,这将告诉Rust在另一个与模块同名的文件中加载模块的内容

常用集合

vrctor

  1. 新建
    1. let v:Vec = Vec::new();
    2. let v = vec![1,2,3];
  2. 更新 push
  3. 读取 索引语法(&v[下标]) 或者 get()(返回一个Option<&T>)
  4. (执行所有权和借用规则)不能在相同作用域中同时存在可变和不可变引用的规则
  5. 遍历 **for i in & (mut) v {} **
  6. 更多参考文档

使用字符串存储utf-8编码的文本

  1. Rust 的核心语言中只有一种字符串类型:str,字符串 slice,它通常以被借用的形式出现,&str;
  2. 创建字符串 String::new(); String::from(“abc”); “abc”.to_string();
  3. 更新字符串push_str();push(); 使用+运算符 (let s3 = s1 + &s2; // 注意 s1 被移动了,不能继续使用)或format! 宏拼接字符串
  4. 索引字符串 s1[0]
  5. slice 字符串
  6. for c in “字符串”.chars(){}

哈希map存储键值对

  1. 新建 HashMap::new(); HashMap<,> 可以使用下划线占位,而 Rust 能够根据 数据的类型推断出 HashMap 所包含的类型。
  2. insert(插入、覆盖) get(获取) entry(是否存中)

错误处理

panic!与不可恢复的错误

  1. Rust 有 panic!宏。当执行这个宏时,程序会打印出一个错误信息,展开并清理栈数据,然后接着退出
  2. 当出现 panic 时,程序默认会开始 展开((unwinding),这意味着 Rust 会回溯栈并清理它遇到的每一个函数的数据,不过这个回溯并清理的过程有很多工作。另一种选择是直接 终止(abort),这会不清理数据就退出程序。**panic 时通过在 Cargo.toml 的 [profile] 部分增加 panic = ‘abort’,可以由展开切换为终止。例如,如果你想要在release模式中 panic 时直接终止 [profile.release] panic = ‘abort’ **
  3. RUST_BACKTRACE 环境变量来得到一个 backtrace ** RUST_BACKTRACE=1 cargo run**

Rusult 与可恢复的错误

  1. Result<T,E>
  2. 失败时panic的简写:unwrap(unwrap 会为我们调用 panic!)和expect( 输出失败信息)
  3. 传播错误:当编写一个其实现会调用一些可能会失败的操作的函数时,除了在这个函数中处理错误外,还可以选择让调用者知道这个错误并决定该如何处理。
  4. 传播错误的简写:?运算符

泛型、trait、生命周期

泛型数据类型

  1. Rust 通过在编译时进行泛型代码的 单态化(monomorphization)来保证效率。单态化是一个通过填充编译时使用的具体类型,将通用代码转换为特定代码的过程。

trait :定义共享的行为

  1. trait 告诉 Rust 编译器某个特定类型拥有可能与其他类型共享的功能。可以通过 trait 以一种抽象的方式定义共享的行为。可以使用 trait bounds 指定泛型是任何拥有特定行为的类型。**注意:trait 类似于其他语言中的常被称为 接口(interfaces)的功能,虽然有一些不同。 **
  2. trait 定义是一种将方法签名组合起来的方法,目的是定义一个实现某些目的所必需的行为的集合。
  3. 例如:pub trait Summary { fn summarize(&self) -> String; }; 实现 使用 impl trait名称 for 目标{fn… }
  4. 实现 trait 时需要注意的一个限制是,只有当 trait 或者要实现 trait 的类型位于 crate 的本地作用域时,才能为该类型实现 trait。
  5. 但是不能为外部类型实现外部 trait
  6. trait中的方法可有默认实现。
  7. trait作为参数: fn 方法名(item: impl trait名){ … }
  8. trait bound 语法糖 fn 方法名 <T : trait名>( item:T){ … }
  9. 在<T : trait名> 还可使用 + 或者使用 where fn some_function<T, U>(t: T, u: U) -> i32 where T: Display + Clone, U: Clone + Debug { … }
  10. 也可在返回值中使用 impl Trait语法 ,返回一个只是指定了需要实现的 trait 的类型的能力在闭包和迭代器场景十分的有用
  11. 通过使用带有 trait bound 的泛型参数的 impl 块,可以有条件地只为那些实现了特定 trait 的类型实现方法。

生命周期和引用有效性

  • Rust 中的每一个引用都有其 生命周期(lifetime),也就是引用保持有效的作用域。
  • 生命周期避免了悬垂引用。它会导致程序引用了非预期引用的数据。
  • 生命周期注解语法
    • &i32 // 引用
    • &'a i32 // 带有显式生命周期的引用
    • &'a mut i32 // 带有显式生命周期的可变引用
  • 泛型生命周期
  • 当从函数返回一个引用,返回值的生命周期参数需要与一个参数的生命周期参数相匹配。如果返回的引用 没有 指向任何一个参数,那么唯一的可能就是它指向一个函数内部创建的值,它将会是一个悬垂引用,因为它将会在函数结束时离开作用域。
  • 生命周期语法是用于将函数的多个参数与其返回值的生命周期进行关联的。一旦他们形成了某种关联,Rust 就有了足够的信息来允许内存安全的操作并阻止会产生悬垂指针亦或是违反内存安全的行为。
  • 结构体定义中的生命周期注解
    • 我们将定义包含引用的结构体,不过这需要为结构体定义中的每一个引用添加生命周期注解
  • 被编码进 Rust 引用分析的模式被称为 **生命周期省略规则 **
    • 第一条规则是每一个是引用的参数都有它自己的生命周期参数。换句话说就是,有一个引用参数的函数有一个生命周期参数:fn foo<'a>(x: &'a i32),有两个引用参数的函数有两个不同的生命周期参数,fn foo<'a, 'b>(x: &'a i32, y: &'b i32),依此类推。
    • 第二条规则是如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数fn foo<'a>(x: &'a i32) -> &'a i32
    • 第三条规则是如果方法有多个输入生命周期参数并且其中一个参数是 &self 或 &mut self,说明是个对象的方法(method) ,那么所有输出生命周期参数被赋予 self 的生命周期。第三条规则使得方法更容易读写,因为只需更少的符号。
  • **静态生命周期 **
    • ** 'static **,其生命周期能够存活于整个程序期间

测试

编写测试

  • #[test]注解 方法上使用
  • assert_eq!宏 相等 assert_ne! 不相等
  • 使用 assert! 宏来检查结果
  • assert!、assert_eq! 和 assert_ne! 宏传递一个可选的失败信息参数,可以在测试失败时将自定义失败信息一同打印出来
  • 使用 #[should_panic] 检查 panic ,检查方法打印值是否相同
  • Result<T, E> 用于测试作为返回值

相关文章:

Rust语言学习

Rust语言学习 通用编程概念所有权所有权引用和借用slice struct(结构体)定义并实例化一个结构体使用结构体方法语法 枚举 enums定义枚举match控制流运算符if let 简单控制流 使用包、Crate和模块管理不断增长的项目&#xff08;模块系统&#xff09;包和crate定义模块来控制作用…...

AI比人脑更强,因为被植入思维模型【16】反脆弱

毛选中就有言&#xff0c;不经历困难&#xff0c;我们就不会掌握战胜困难的方法。 这个世界纷繁复杂&#xff0c;不是强者总是运气好&#xff0c;而是他们能够失败后快速复原&#xff0c;不断找到战胜困难的方法。 定义 马斯洛需求层次模型是一种将人类需求从低到高按层次进…...

系统架构设计知识体系总结

1.技术选型 1.什么是技术选型&#xff1f; 技术选型是指评估和选择在项目或系统开发中使用的最合适的技术和工具的过程。这涉及考虑基于其能力、特性、与项目需求的兼容性、可扩展性、性能、维护和其他因素的各种可用选项。技术选型的目标是确定与项目目标相符合、能够有效解…...

计算机视觉的多模态模型

计算机视觉的多模态模型 是指能够同时处理和理解 多种类型数据&#xff08;模态&#xff09; 的模型。这些模态可以包括图像、文本、音频、视频、深度信息等。多模态模型的核心目标是利用不同模态之间的互补信息&#xff0c;提升模型的性能和泛化能力。 1. 多模态模型的核心思想…...

Scrapy 入门教程

Scrapy 入门教程 Scrapy 是一个用于爬取网站数据的 Python 框架&#xff0c;功能强大且易于扩展。本文将介绍 Scrapy 的基本概念、安装方法、使用示例&#xff0c;并展示如何编写一个基本的爬虫。 1. 什么是 Scrapy&#xff1f; Scrapy 是一个开源的、用于爬取网站数据的框架…...

Oracle OCP认证是否值得考?

Oracle OCP&#xff08;Oracle Certified Professional&#xff09;认证是数据库领域的传统权威认证&#xff0c;但随着云数据库和开源技术的崛起&#xff0c;其价值正面临分化。是否值得考取&#xff0c;需结合你的职业定位、行业需求及长期规划综合判断。以下是关键分析&…...

OpenCV中距离公式

一、各类距离公式总结 常见距离公式 欧氏距离&#xff1a; 曼哈顿距离&#xff08;L1&#xff09;‌&#xff1a; 切比雪夫距离&#xff08;Chessboard&#xff09;‌&#xff1a; 1、点与点距离(欧氏距离) ‌二维空间‌ 设两点坐标为 P1(x1,y1)、P2(x2,y2)&#xff0c;其距离…...

DeepSeek自学手册:《从理论(模型训练)到实践(模型应用)》|73页|附PPT下载方法

导 读INTRODUCTION 今天分享是由ai呀蔡蔡团队带来的DeepSeek自学手册&#xff1a;《从理论&#xff08;模型训练&#xff09;到实践&#xff08;模型应用&#xff09;》&#xff0c;这是一篇关于DeepSeek模型训练、应用场景及替代方案的综合指南文章&#xff0c;主要介绍了Deep…...

Doris官网上没有的一些Fe参数了,都在源码中

一、FE配置源码 apache-doris-src\fe\fe-common\src\main\java\org\apache\doris\common\Config.java 二、BE配置源码 apache-doris-src\be\src\common\config.cpp 三、FE源码 package org.apache.doris.common;public class Config extends ConfigBase {ConfField(descri…...

(一)丶Windows安装RabbitMQ可能会遇到的问题

一丶可能会忘了配置ERLang的环境变量 二丶执行命令时报错 第一步 rabbitmq-plugins enable rabbitmq_management 第二部 rabbitmqctl status 三丶修改.erlang.cookie 文件 1.找到C盘目下的.erlang.cookie文件 C:\Users\admin\.erlang.cookie C:\Windows\System32\config\sys…...

stm32g030移植RT-Thread

移植流程 移植前需要安装Keil.STM32G0xx_DFP.1.2.0.pack组件&#xff0c;大致的移植过程&#xff1a; CubeMX配置RT-Thread组件配置工程模板配置 参考例程配置&#xff1a;拷贝仓库原有的stm32g070-st-nucleo工程&#xff0c;然后另起一个名字&#xff0c;目录结构如下 完整…...

Parsing error: Unexpected token, expected “,“

今天在使用Trae AI 编程工具开发大文件切片上传功能&#xff0c;使用的是VUE3,TS技术栈&#xff0c;开发完成运行时&#xff0c;编译报错&#xff08;Parsing error: Unexpected token, expected ","&#xff09;&#xff0c;让AI自行修复此问题多次后还是没有解决&a…...

Day23: 数组中数字出现的次数

整数数组 sockets 记录了一个袜子礼盒的颜色分布情况&#xff0c;其中 sockets[i] 表示该袜子的颜色编号。礼盒中除了一款撞色搭配的袜子&#xff0c;每种颜色的袜子均有两只。请设计一个程序&#xff0c;在时间复杂度 O(n)&#xff0c;空间复杂度O(1) 内找到这双撞色搭配袜子的…...

目标检测——清洗数据

清洗VOC格式数据集代码示例 import os import xml.etree.ElementTree as ETdef process_annotations(image_folder, annotation_folder):# 遍历标签文件夹中的所有XML文件for xml_file in os.listdir(annotation_folder):if not xml_file.endswith(.xml):continuexml_path os…...

嵌入式基础知识学习:UART是什么?

UART&#xff08;Universal Asynchronous Receiver/Transmitter&#xff0c;通用异步收发传输器&#xff09;是一种广泛应用于嵌入式系统和通信设备的异步串行通信协议。它通过两根数据线&#xff08;TX和RX&#xff09;实现设备间的全双工数据传输&#xff0c;无需共享时钟信号…...

SpringBoot项目实战(初级)

目录 一、数据库搭建 二、代码开发 1.pom.xml 2.thymeleaf模块处理的配置类 3.application配置文件 4.配置&#xff08;在启动类中&#xff09; 5.编写数据层 ②编写dao层 ③编写service层 接口 实现类 注意 补充&#xff08;注入的3个注解&#xff09; 1.AutoWir…...

合成层优化

以下是关于 合成层(Composite Layer)优化 的系统梳理,涵盖基础原理、触发条件、优化策略及进阶实践,帮助深入理解如何通过分层渲染提升页面性能: 一、合成层基础概念 1. 什么是合成层? 定义:浏览器将页面元素提升为独立的图形层(Graphics Layer),由 GPU 单独处理,避…...

什么是MCP|工作原理是什么|怎么使用MCP|图解MCP

写在前面 Manus的爆火似乎推动了MCP的出圈&#xff0c;虽然Manus没有用MCP。这篇文章我们就讲讲MCP&#xff0c;当然我也是最近才学习到MCP的&#xff0c;如果理解有误的地方&#xff0c;欢迎评论区指出&#xff01; 1. 为什么需要MCP&#xff1f; 1.1 LLM 现状 我们都知道…...

《Partial-label learning with a guided Prototypical classifier》23年CVPR 文献速读

论文地址 1. 引言 本文介绍了一种用于部分标签学习&#xff08;Partial-Label Learning, PLL&#xff09;的新框架 PaPi&#xff08;Partial-label learning with a guided Prototypical classifier&#xff09;&#xff0c;旨在提高在视觉任务中处理部分标签数据时的性能。部…...

GitLens with `Commit Graph`

文章目录 GitLens with Commit Graph GitLens with Commit Graph 自己打包的 GitLens&#xff0c;能够查看 commit graph。 GitLens 持续更新中 下载之后&#xff0c;通过 VSCode 插件直接安装即可使用。...

python每日十题(6)

】函数定义&#xff1a;函数是指一组语句的集合通过一个名字&#xff08;函数名&#xff09;封装起来&#xff0c;要想执行这个函数&#xff0c;只需要调用其函数名即可。函数能提高应用的模块性和代码的重复利用率 在Python语言中&#xff0c;用关键字class来定义类 在Python语…...

UniRel论文复现过程中的问题解决办法(全)

注解写在前面&#xff1a;本文仅为解决各位同学在复现时面对的问题&#xff0c;有问题可以评论&#xff0c;看见会回复&#xff01;&#xff01;&#xff01; [顶刊论文]UniRel:Unified Representation and Interaction for Joint Relational Triple Extraction2022.11.16&…...

js逆向之断点调试

1.XHR/提取断点用法 当刷新页面时候&#xff0c;有大量请求&#xff0c;并且你无法定位参数信息的时候&#xff0c;或者参数被混淆无法搜到&#xff0c;可以用该方法&#xff0c;该方法是会捕获所有请求连接&#xff0c;然后我们通过连接过滤出自己想要的请求&#xff0c;然后…...

Unity Shader编程】之渲染流程之深度及pass详解

关于透明物体的渲染&#xff0c;首先需要了解以下部分 深度缓冲区深度写入深度测试pass渲染和深度测试的过程深度测试和颜色混合过程 ** 一&#xff0c;深度缓冲区 ** 深度即物体距离相机的距离&#xff0c;深度写入即是把物体的距离相机信息记录下来&#xff0c;写入一个名…...

【算法笔记】图论基础(一):建图、存图、树和图的遍历、拓扑排序、最小生成树

目录 何为图论图的概念 图的一些基本概念有向图和无向图带权图连通图和非连通图对于无向图对于有向图 度对于无向图对于有向图一些结论 环自环、重边、简单图、完全图自环重边简单图 稀疏图和稠密图子图、生成子图同构 图的存储直接存边邻接矩阵存边邻接表存边链式前向星存边 图…...

Compose 原理解析

Compose 的组件都是放在 setContent() 之后才能显示的&#xff0c;那需要先看看这个函数的作用。 先看 ComponentActivity 的扩展函数 setContent()&#xff1a; /*** 将给定的可组合项合成到给定的 Activity 中。[content] 将成为给定 Activity 的根视图。* 这大致相当于使用…...

pyspark学习rdd处理数据方法——学习记录

python黑马程序员 """ 文件&#xff0c;按JSON字符串存储 1. 城市按销售额排名 2. 全部城市有哪些商品类别在售卖 3. 上海市有哪些商品类别在售卖 """ from pyspark import SparkConf, SparkContext import os import jsonos.environ[PYSPARK_P…...

个人学习编程(3-22) leetcode刷题

连续子数组&#xff1a;&#xff08;难&#xff09; 示例 1: 输入: nums [0,1] 输出: 2 说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。 示例 2: 输入: nums [0,1,0] 输出: 2 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。 需要理解的知识&a…...

RabbitMQ八股文

RabbitMQ 核心概念与组件 1. RabbitMQ 核心组件及其作用 1.1 生产者&#xff08;Producer&#xff09; 作用&#xff1a;创建并发送消息到交换机。特点&#xff1a;不直接将消息发送到队列&#xff0c;而是通过交换机路由。 1.2 交换机&#xff08;Exchange&#xff09; 作…...

运维面试题(七)

1.statefulset用来管理有状态的应用程序&#xff0c;有状态是什么意思&#xff1f; 每一个pod都有一个固定的网络标识符&#xff0c;在整个生命周期中不会改变。每个实例都可以拥有自己的持久化存储卷&#xff0c;即使容器被删除并重新创建&#xff0c;存储卷仍然存在。Statef…...

【项目设计】网页版五子棋

文章目录 一、项目介绍1.项目简介2.开发环境3.核心技术4.开发阶段 二、Centos-7.6环境搭建1.安装wget工具2.更换软件源(yum源)3.安装scl工具4.安装epel软件源5.安装lrzsz传输工具6.安装高版本gcc/g编译器7.安装gdb调试器8.安装git9.安装cmake10.安装boost库11.安装Jsoncpp库12.…...

Netty——BIO、NIO 与 Netty

文章目录 1. 介绍1.1 BIO1.1.1 概念1.1.2 工作原理1.1.3 优缺点 1.2 NIO1.2.1 概念1.2.2 工作原理1.2.3 优缺点 1.3 Netty1.3.1 概念1.3.2 工作原理1.3.3 优点 2. Netty 与 Java NIO 的区别2.1 抽象层次2.2 API 易用性2.3 性能优化2.4 功能扩展性2.5 线程模型2.6 适用场景 3. 总…...

Docker 安装 Mysql

以下是安装Docker版MySQL 8.0.25并实现目录挂载的步骤&#xff1a; docker仓库&#xff1a;https://hub.docker.com/_/mysql 1. 拉取Mysql镜像文件 docker pull mysql:8.0.252. 创建mysql临时容器服务 docker run -d \--name mysql \-p 3306:3306 \-e MYSQL_ROOT_PASSWORD123…...

Electron打包文件生成.exe文件打开即可使用

1 、Electron 打包&#xff0c;包括需要下载的内容和环境配置步骤 注意&#xff1a;Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台桌面应用程序的框架 首先需要电脑环境有Node.js 和 npm我之前的文章有关nvm下载node的说明也可以去官网下载 检查是否有node和npm环…...

线程和协程的区别了解

1.资源消耗 调度方式&#xff1a;线程由操作系统内核调度&#xff08;抢占式&#xff09;&#xff0c;协程由程序自己控制调度&#xff08;协作式&#xff09;。切换开销&#xff1a;线程切换涉及内核态与用户态的转换&#xff0c;开销大&#xff1b;协程只在用户态切换上下文…...

楼宇自控系统的结构密码:总线与分布式结构方式的差异与应用

在现代建筑中&#xff0c;为了实现高效、智能的管理&#xff0c;楼宇自控系统变得越来越重要。它就像建筑的 智能管家&#xff0c;可自动控制照明、空调、通风等各种机电设备&#xff0c;让建筑运行更顺畅&#xff0c;还能节省能源成本。而在楼宇自控系统里&#xff0c;有两种关…...

算法及数据结构系列 - 滑动窗口

系列文章目录 算法及数据结构系列 - 二分查找 算法及数据结构系列 - BFS算法 算法及数据结构系列 - 动态规划 算法及数据结构系列 - 双指针 算法及数据结构系列 - 回溯算法 算法及数据结构系列 - 树 文章目录 滑动窗口框架思路经典题型76. 最小覆盖子串567. 字符串的排列438. …...

【江协科技STM32】软件SPI读写W25Q64芯片(学习笔记)

SPI通信协议及S为5Q64简介&#xff1a;【STM32】SPI通信协议&W25Q64Flash存储器芯片&#xff08;学习笔记&#xff09;-CSDN博客 STM32与W25Q64模块接线&#xff1a; SPI初始化&#xff1a; 片选SS、始终SCK、MOSI都是主机输出引脚&#xff0c;输出引脚配置为推挽输出&…...

2025.3.23机器学习笔记:文献阅读

2025.3.23周报 题目信息摘要Abstract创新点网络架构实验不足以及展望 题目信息 题目&#xff1a; Enhancement of Hydrological Time Series Prediction with Real-World Time Series Generative Adversarial Network-Based Synthetic Data and Deep Learning Models期刊&…...

Day20-前端Web案例——部门管理

目录 部门管理1. 前后端分离开发2. 准备工作2.1 创建Vue项目2.2 安装依赖2.3 精简项目 3. 页面布局3.1 介绍3.2 整体布局3.3 左侧菜单 4. Vue Router4.1 介绍4.2 入门4.3 案例4.4 首页制作 5. 部门管理5.1部门列表5.1.1. 基本布局5.1.2 加载数据5.1.3 程序优化 5.2 新增部门5.3…...

实验3 以太坊交易周期的需求分析

区块链技术 实验报告 实验名称 实验3 以太坊交易周期的需求分析 一、实验目的 1、学习并掌握以太坊交易的内容&#xff1b; 2、学习并掌握以太坊交易周期的四个阶段&#xff1b; 3、学习并掌握结构化需求分析方法&#xff1b; 4、学习并掌握面向对象的需求分析方法&…...

Linux 通过压缩包安装 MySQL 并设置远程连接教程

一、引言 在 Linux 系统中,有时候我们需要通过压缩包的方式手动安装 MySQL 数据库,并且为了方便在其他设备上对数据库进行管理和操作,还需要设置允许远程连接。本文将详细介绍在 Linux(以 CentOS 为例)系统中通过压缩包安装 MySQL 8 并设置远程连接的步骤。 二、安装前准…...

【商城实战(56)】商城数据生命线:恢复流程与演练全解析

【商城实战】专栏重磅来袭&#xff01;这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建&#xff0c;运用 uniapp、Element Plus、SpringBoot 搭建商城框架&#xff0c;到用户、商品、订单等核心模块开发&#xff0c;再到性能优化、安全加固、多端适配&#xf…...

Java学习笔记-XXH3哈希算法

XXH3是由Yann Collet设计的非加密哈希算法&#xff0c;属于XXHash系列的最新变种&#xff0c;专注于极速性能与低碰撞率&#xff0c;适用于对计算效率要求极高的场景。 极速性能 在RAM速度限制下运行&#xff0c;小数据&#xff08;如 1-128 字节&#xff09;处理可达纳秒级&…...

同旺科技USB to SPI 适配器 ---- 指令循环发送功能

所需设备&#xff1a; 内附链接 1、同旺科技USB to SPI 适配器 1、周期性的指令一次输入&#xff0c;即可以使用 “单次发送” 功能&#xff0c;也可以使用 “循环发送” 功能&#xff0c;大大减轻发送指令的编辑效率&#xff1b; 2、 “单次发送” 功能&#xff0c;“发送数据…...

在Mac M1/M2芯片上完美安装DeepCTR库:避坑指南与实战验证

让推荐算法在Apple Silicon上全速运行 概述 作为推荐系统领域的最经常用的明星库&#xff0c;DeepCTR集成了CTR预估、多任务学习等前沿模型实现。但在Apple Silicon架构的Mac设备上&#xff0c;安装过程常因ARM架构适配、依赖库版本冲突等问题受阻。本文通过20次环境搭建实测…...

【CXX-Qt】2.5 继承

某些 Qt API 要求你从抽象基类中重写某些方法&#xff0c;例如 QAbstractItemModel。 为了支持直接从 Rust 中创建这样的子类&#xff0c;CXX-Qt 提供了多种辅助工具。 某些基类可能需要特殊的构造参数。这可以通过使用自定义构造函数来实现。 访问基类方法 要在 Rust 中访…...

Linux系统之美:环境变量的概念以及基本操作

本节重点 理解环境变量的基本概念学会在指令和代码操作上查询更改环境变量环境变量表的基本概念父子进程间环境变量的继承与隔离 一、引入 1.1 自定义命令&#xff08;我们的exe&#xff09; 我们以往的Linux编程经验告诉我们&#xff0c;我们在对一段代码编译形成可执行文件后…...

【nnUnetv2】推理+评估+测试

在 Windows 系统下设置环境变量 之前训练和推理的时候开着AutoDL的服务器,是在 Linux 系统下设置的环境变量。 但是现在开始研究具体代码了,就在本地跑(一直开着服务器有点费钱),所以就在Windows 系统下设置环境变量。 ①右键点击 “此电脑”,选择 “属性”。 ②在左侧…...

损失函数理解(一)——极大似然估计

本博客内容来自B站up主【王木头学科学】的视频内容 习惯看视频的小伙伴可移至视频链接[待补充]&#xff1a;~~~ 首先通俗地解释一下极大似然估计&#xff08;Maximum Likelihood Estimation&#xff0c;MLE&#xff09;的思想&#xff1a;通过结果寻找使该结果发生的最可能的原…...