ts 详细-学习

TS基础(一) 变量声明

ts的类型主要包括两种数据类型:原始数据类型和对象数据类型

原始数据类型和js的数据类型相似包括以下几种:布尔值,字符串,null,undefined以及Se6中的Symbol和BigInt的原址数据类型

//布尔类型
let done :boolean = false
//数值类型
let age :number  =1
//字符串类型
let name = "view"
let age:number = undefined
......

注意:所有的包装类型返回的是包装类型比如Boolean

let done:Boolean = new Boolean(1)
let complete:boolean = Boolean(1) //这是相当于调用普通函数声明返回值

2.原始类型的字符是没有对应的方法的,那么为什么像字符串可以调用valueOf方法了。这是因为在运行的时候,原始类型会重新被包装类型初始化。获得一个新的包装类型对象,包装类型对象有相应的方法,在执行完毕这条代码的时候,生成的包装类型也相应的删除回收掉。实例如下。这个过程在java过程叫做拆箱和装箱

let name :string ="view"
console.log(name.length())
//在运行时候处理如下
//执行到name.length()之后,系统会如下处理
let value :String  = new String(name)
value.length()
//删除,回收掉value

TS基础(二)变量声明 任意类型 any

任意类型定义(any):用来可以赋值给任意类型的类型
在TS中一个普通类型的数据在赋值的过程中因为类型已经被定义了,在原型过程中不能被随意改变

let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.

TS基础(三)类型推断

类型推断指的是:数据没有指定明确的类型,那么ts会按照类型推论的规则推断出一个类型

let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
//myFavoriteNumber  被推断成字符串了,不在能被赋值给数值型数据了
// index.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.

有一种情况需要注意,如果定数变量的时候,如果没有赋值初始值,那么它会推断成任意类型,之后再赋值,它也会被推断成任意类型

let myFavoriteNumber;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

TS基础(四)联合类型

联合类型表示取值可以参考多种类型中的一种。联合类型使用|来对多种类型进行分割

let myFavoriteNumber: string | number;myFavoriteNumber = 'seven';myFavoriteNumber = 7;  

联合类型在实际的使用中可以使用type来定义,可以是类型声明更贱简洁

 type m =  string | numberlet c:m  ;c = 1;c = "11"

Ts不确定联合类型不确定变量使用哪种类型的时候,我们只能访问联合类型中共有属性和方法

function getLength(something: string | number): number {return something.length;
}
//length属性number不存在
// index.ts(2,22): error TS2339: Property 'length' does not exist on type 'string | number'.
//   Property 'length' does not exist on type 'number'.

联合类型的变量在赋值的时候,会根据赋值类型推断出规则中的一个类型

myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length); // 5
myFavoriteNumber = 7;
console.log(myFavoriteNumber.length); // 编译时报错  myFavoriteNumber已经被推断为number类型,不存在length属性// index.ts(5,30): error TS2339: Property 'length' does not exist on type 'number'.

TS基础(五)接口

TS中接口是用来定义对象的类型。TS中接口和泛型属于十分重要的类型。
在面向对象语言中,接口它是对行为的抽象,行动由类(Class)去实现(Implement),一个类可以实现多个接口

接口(interface)定义对象的类型

interface Person {name: string;age: number;
}let tom: Person = {name: 'Tom',age: 25
};

使用接口定义对象的时候,定义的类型比接口少是不允许的,多一些属性也是不允许的

interface Person {name: string;age: number;
}let tom: Person = {name: 'Tom'
};// index.ts(6,5): error TS2322: Type '{ name: string; }' is not assignable to type 'Person'.
//   Property 'age' is missing in type '{ name: string; }'.interface Person {name: string;age: number;
}let tom: Person = {name: 'Tom',age: 25,gender: 'male'
};

同时接口允许使用可选参数,即在参数后面加上?,表示这个参数可以没有

interface Person {name: string;age?: number;
}let tom: Person = {name: 'Tom',age: 25
};

有时候,需要一个接口允许有任意的属性,可以使用以下方法

interface Person {name: string;age?: number;[propName: string]: any;
}let tom: Person = {name: 'Tom',gender: 'male'
};

使用 [propName: string] 定义了任意属性取 string 类型的值。
注意:一旦定义了任意属性,那么确定属性和可选属性的类型必须是它类型的子类.一般情况下,可以设置任意属性的值类型设置为任意类型(any)

interface Person {name: string;age?: number;[propName: string]: string;
}let tom: Person = {name: 'Tom',age: 25,gender: 'male'
};// index.ts(3,5): error TS2411: Property 'age' of type 'number' is not assignable to string index type 'string'.
// index.ts(7,5): error TS2322: Type '{ [x: string]: string | number; name: string; age: number; gender: string; }' is not assignable to type 'Person'.
//   Index signatures are incompatible.
//     Type 'string | number' is not assignable to type 'string'.
//       Type 'number' is not assignable to type 'string'.

接口也可以使用修饰符号修饰。readonly 代表只读属性

interface Person {readonly id: number;name: string;age?: number;[propName: string]: any;
}let tom: Person = {id: 89757,name: 'Tom',gender: 'male'
};tom.id = 9527;// index.ts(14,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.

注意:只读的约束发生在给对象第一次赋值的时候,而不是只读属性赋值的时候

interface Person {readonly id: number;name: string;age?: number;[propName: string]: any;
}let tom: Person = {
//已经赋值过name: 'Tom',gender: 'male'
};tom.id = 89757; //重复赋值// index.ts(8,5): error TS2322: Type '{ name: string; gender: string; }' is not assignable to type 'Person'.
//   Property 'id' is missing in type '{ name: string; gender: string; }'.
// index.ts(13,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.

约束类型构造类型,使用new来约束

new():A :表示接受一个构造参数

 class  AnimalA {constructor(public name:string) {}}interface withAnimal {new (c:string):AnimalA //表示该接口中必须需要一个构造函数}function createAnimal(clzz:withAnimal,name:string){return new clzz(name)}createAnimal(AnimalA,"zw")

TS基础(六)数组类型

第一种【类型+方括号】表示方法 string[]

let fibonacci: number[] = [1, 1, 2, 3, 5]; //定义一个数值数组

数组中不允许出现其他的类型

let fibonacci: number[] = [1, '1', 2, 3, 5];// Type 'string' is not assignable to type 'number'.

也对数组的方法进行了限制

let fibonacci: number[] = [1, 1, 2, 3, 5];
fibonacci.push('8');// Argument of type '"8"' is not assignable to parameter of type 'number'.

第二种 数组泛型 Array<T>

let fibonacci: Array<number> = [1, 1, 2, 3, 5];

第三种 用接口表示数组

interface NumberArray {[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];

第四种 用接口表示数组

    let args: {[index: number]: number;length: number;callee: Function;} = arguments;
}

TS基础(七)函数

在JavaScript中函数是一等公民。有两种常见定义函数的方式,函数声明和函数表达式。函数声明和函数表达式还是有稍微的区别:函数声明有变量提升的作用

// 函数声明(Function Declaration)
function sum(x, y) {return x + y;
}// 函数表达式(Function Expression)
let mySum = function (x, y) {return x + y;
};

函数有输入和输出,要在TS中对齐进行约束。需要把输入和输出考虑到,其中比较简单的定义如下

function sum(x: number, y: number): number {return x + y;
}

使用接口约束函数

可以使用接口的方式来定义一个函数需要符合条件的形状

interface SearchFunc {(source: string, subString: string): boolean;
}let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {return source.search(subString) !== -1;
}

使用接口来定义函数的目的主要有如下几个方面的好处
1:当一个函数当参数传递的时候,可以清楚知道函数的信息。
2:可以保证以后函数参数个数,返回值类型不改变

函数可选参数

输入多余的参数是不被允许的,但是如果参数使用?,那么表示这个参数是可以不传递的。
注意:带?的参数,写在最后才能被省略,否则会报错

function buildName(firstName: string, lastName?: string) {if (lastName) {return firstName + ' ' + lastName;} else {return firstName;}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
function buildName(firstName?: string, lastName: string) {if (firstName) {return firstName + ' ' + lastName;} else {return lastName;}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName(undefined, 'Tom');// index.ts(1,40): error TS1016: A required parameter cannot follow an optional parameter.

参数默认值

ES6中参数支持默认值,TS中同样支持默认值

function buildName(firstName: string, lastName: string = 'Cat') {return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');

省略参数

//...items 代表省略参数,是一个数组
function push(array: any[], ...items: any[]) {items.forEach(function(item) {array.push(item);});
}let a = [];
push(a, 1, 2, 3);

函数重载

重载允许一个函数接口不同数量不同类型的参数时候,做出不同的处理。重载样式如下

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {if (typeof x === 'number') {return Number(x.toString().split('').reverse().join(''));} else if (typeof x === 'string') {return x.split('').reverse().join('');}
}

TS基础(八)类型断言

是一种告诉编译器你对某个值的类型有比编译器更准确的了解的方式。这通常用于当你确定某个值的类型,但编译器无法推断出这个类型时。类型断言有两种形式:尖括号语法和as语法

语法:值as类型或者<类型>值

在tsx中必须使用前者

类型断言用途

讲一个联合类型断言为其中一个类型

interface Cat {name: string;run(): void;
}
interface Fish {name: string;swim(): void;
}function isFish(animal: Cat | Fish) {
//这里讲animal 断言成Fish对象 强制类型转换,运行报错if (typeof (animal as Fish).swim === 'function') {return true;}return false;
}

注意:类型断言只是七篇编译器,让编译器可以通过,但是图个强制类型转换,让执行的过程中回报错

尖括号语法

let someValue: any = "this is a string";let strLength: number = (<string>someValue).length;

as语法

let someValue: any = "this is a string";let strLength: number = (someValue as string).length;

非空断言

在ts中当你确定某个变量不是null或undefind时,可以使用非空断言操作符 |,这会从类型中一处null和undefind

let mayNullOrUndefinedValue: string | null | undefined = "Hello";let length: number = mayNullOrUndefinedValue!.length; // 使用非空断言

可以将任意类型断言成any类型

总结:

1.联合类型可以被断言成其中一个类型

2.父类可以断言成子类

3.任何类型可以断言成any'

4.any可以断言成any

TS基础(九)类型别名

类型别名一般用于给一个联合类型取新的名字,对代码的整洁还时有很大的帮助

    type c = number | string | booleanlet a :c= 10 
interface 和type区别

1.interface只能定义对象类型,和type可以定义组合类型,和原始类型。如果type声明的,会导致一些功能缺失

2.interface可以实现接口merge,但是type不行

interface merage 合并实例

   interface A{a:number }interface A{b:number }let C :A ={a:10,b:20}

 

TS基础(十)字符串字面量类型

字符串字面量类型用来约束取值只能是某几个字符中的一个

type EventNames = 'click' | 'scroll' | 'mousemove'function handleEvent(el:EventNames) :void{}handleEvent('click')

 注意:当字符串作为类型的时候,表示的是一种类型,而不是一个赋值。切记

TS基础(十一)元组

数组合并想用类型的对象,而元素(Tuple)合并了不同类型的对象

元素可以属于理解成一个任意类型并且长度有限的数组

简单的例子

let tom: [string, number] = ['Tom', 25];
let tom: [string, number];
tom[0] = 'Tom';
tom[1] = 25;tom[0].slice(1);
tom[1].toFixed(2);

元素越界

当添加的元素越界的时候,越界的类型会被限制为元素类型的联合类型

let tom: [string, number];
tom = ['Tom', 25];
tom.push('male');
tom.push(true);

TS基础(十二)枚举enum

枚举类型定义取值被限定在一定范围内的场景

enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

枚举成员会被赋值从0开始递增的数字,同时也会对枚举值到枚举名进行反射

enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // trueconsole.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true
console.log(Days[2] === "Tue"); // true
console.log(Days[6] === "Sat"); // true

 枚举手动赋值

枚举支持手动赋值,当使用手动赋值之后的所有都会街上上一个枚举递增

enum Days {Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat};console.log(Days["Sun"] === 3); // true
console.log(Days["Wed"] === 3); // true
console.log(Days[3] === "Sun"); // false
console.log(Days[3] === "Wed"); // true

 常数枚举和计算所的枚举

常数枚举使用const定义的枚举类型

const enum Directions {Up,Down,Left,Right
}let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

常数枚举和普通枚举的区别,它在编译阶段被删除,并且不能包含计算成员

//编译结果
var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];

计算所得枚举

计算机枚举就是一个枚举中使用计算方法组合成的一个枚举。当前面的一个枚举成员是计算得到的,那么下一个枚举成员需要进行手动赋值,不然会因为初始值而报错

enum Color {Red = "red".length, Green, Blue};// index.ts(1,33): error TS1061: Enum member must have initializer.
// index.ts(1,40): error TS1061: Enum member must have initializer.

void 类型

如果一个函数没有返回值那么它返回值的类型就是 void。

let fun4 = (num1: number, num2: number): void => {console.log(num1, num2);
};
fun4(11, 22);

泛型

泛型可以在保证类型安全的前提下让函数等多种类型一起工作从而实现服用,泛型在保护类型安全的同时,也可以让函数等多种不同的类型一起工作,实现服用。

想要函数之类的做到可以同时支持多种不同的类型,有可以做到类型的安全,此时可以使用泛型

泛型基本使用

function id<type>(item: type): type {return item;
}
interface obj {name: string;
}
console.log(id<number>(1111));
console.log(id<string>("!!!!!!!!!!!!!!!!!"));
console.log(id<obj>({ name: "Q" }));

 定义泛型的语法是function xxx<type> {item:type} :type{return item},<> 里的内容是调用者传过来的类型这个type是一个类型变量存放的是类型而不是值

这样就可以做到传入值的类型和返回值想和她,也可以答道服用效果

调用的语法 :funName<type>{}. type 就是传递过期的类型

简化调用泛型函数

function id<type>(item: type): type {return item;
}
let str = id("11");
在调用泛型函数是,可以把 <> 去掉达到简写调用,因为 TS 会根据传递实参自动推断出类型。比如传的是 'Q' 那么 TS 会自动推断出是 string 的类型,但如果无法推断出或推断出的类型不准确时就要自己手动传递类型。

泛型约束

添加泛型约束的作用是收缩类型,以免想用某些属性的时候不能用。添加泛型约束主要有两种方式:

  1. 指定具体类型

  2. 添加约束

如果不添加约束的话无法访问任何属性,因为泛型可以代表任何类型,不确定当前类型是否拥有这个属性所以不能访问任何类型。

function fun1<type>(value: type): type {value.length; // 类型“type”上不存在属性“length”return value;
}

指定具体类型

function fun1<type>(value: type[]): type[] {value.length;return value;
}
let str = fun1<string>(["1", "2", "3"]);

上面指定了 value 为 type 类型的数组,所以可以访问 value.length。

添加约束

使用 extends 关键字来添加约束,语法是:<Name extends xxx>,这代表着 Name 的类型必须要满足 xxx。

interface Length {length: number;
}
function fun2<type extends Length>(value: type): type {value.length;return value;
}
let str2 = fun2<number>(1); // 类型“number”不满足约束“Length”
let str3 = fun2<string>("1");

str2 报错是因为传进的类型是 number,但 number 类型没有 length 属性。str3 传的是 string 类型,它有 length 属性所以不报错。

泛型接口

interface NameFun<Type> {name: (value: Type) => Type;names: (value: Type[]) => Type[];
}let obj: NameFun<string> = {name(value) {return value;},names: value => value
};
console.log(obj.name("Q"));
console.log(obj.names(["Q", "Q", "Q"]));

上面的 NameFun 就是一个泛型接口,泛型接口也可以提高接口的复用性。在调用泛型接口的时候跟调用泛型函数一样,都是在 <> 里传递一个类型。在调用的时候传一个 string 然后下方 name 里的 value 就自动是 string 的类型了。

 

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

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

相关文章

VMware虚拟机故障:“显示指定的文件不是虚拟磁盘“,处理办法

一、故障现象 由于虚拟机宕机&#xff0c;强制重新启动虚拟机后显示错误&#xff0c;没有办法启动虚拟机。 虚拟机有快照&#xff0c;执行快照还原&#xff0c;结果也不行&#xff0c;反复操作&#xff0c;在虚拟机文件目录出现很多莫名文件 二、故障原因 根据故障提示&#…

数据结构(C):玩转链表

目录 &#x1f37a;0.前言 1.链表的概念 2.链表的分类 2.1带头不带头 2.2单向和双向 2.3循环和不循环 2.4主要使用的链表 3.链表的实现 3.1申请一个链表 3.2头插和尾插 3.2.1函数的形参问题 3.2.2二级指针问题解决 3.3头删和尾删 3.4打印链表 3.5查找 3.5销…

MySQL视图:数据库中的虚拟表与数据透视窗

前言 在数据库管理系统的世界里&#xff0c;MySQL视图扮演着一个独特而重要的角色&#xff0c;它如同数据库中的一扇窗&#xff0c;透过这扇窗&#xff0c;我们可以以不同的视角观察和操作数据&#xff0c;而无需直接触及底层表格的结构。本文将为您深入解析MySQL视图的定义、…

【谷粒商城】03创建商品模块

1.创建模块 2.创建项目微服务 商品服务、仓储服务、订单服务、优惠券服务、用户服务 共同&#xff1a; 1&#xff09;、web、openfeign 2&#xff09;、每一个服务&#xff0c;包名 com.atguigu.gulimall.xxx(product/order/ware/coupon/member) 3&#xff09;、模块名&#x…

​《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制德国每日风能和太阳能产量3D线图

在MATLAB中&#xff0c;要绘制3D线图&#xff0c;可以使用 plot3 函数。 在《MATLAB科研绘图与学术图表绘制从入门到精通》书中通过绘制德国每日风能和太阳能产量3D线图解释了如何在MATLAB中绘制3D线图。 购书地址&#xff1a;https://item.jd.com/14102657.html

future wait_for()成员、shared_future

future wait_for()成员 wait_for()&#xff1a;等待其异步操作操作完成或者超出等待&#xff0c;用于检查异步操作的状态。wait_for()可以接受一个std::chrono::duration类型的参数&#xff0c;它表示等待的最大时间&#xff0c;会返回一个std::future_status枚举值&#xff0…

完美解决Windows10下-更换JDK环境变量后,在cmd下执行仍java -version然出现原来版本的JDK的问题

一、错误场景预演 本人欲将 JDK 1.8 通过安装包的方式升级为 JDK 22。 本地旧版本&#xff1a;1.8.0_221预升级版本&#xff1a;22.0.1 1.1、查看本地旧版本 在配置环境变量之前&#xff0c;首先我们要明确&#xff0c;本地存在旧版本&#xff0c;如果本地没有 Java&#x…

MFC通过继承现有控件自定义控件

在MFC 自定义控件&#xff0c;可以通过继承MFC提供的控件类&#xff08;如CButton、CEdit、CListBox等&#xff09;并重写其成员函数和消息处理函数来实现。 以下是一个基本的步骤指南&#xff0c;用于在MFC中创建自定义控件&#xff1a; 确定要继承的基类&#xff1a; 首先…

vm16安装最新版本的ubuntu虚拟机,并安装g++的步骤记录

背景 低版本的ubuntu安装G一直不成功&#xff0c;干脆安装最新版的 官网下载 bing搜索ubuntu 下载完成 vm16新建虚拟机 一直下一步&#xff0c;安装完成 终端输入命令 sudo apt-get update ᅟᅠ       sudo apt install gcc ᅟᅠ      sudo apt install g

树莓派点亮FPGA小灯

树莓派点亮FPGA小灯 引言&#xff1a; ​ 本次实验的目的是通过树莓派和FPGA之间的串口通信&#xff0c;控制FPGA开发板上的小灯。实验将展示如何使用树莓派发送特定的字符信号&#xff0c;通过串口传输至FPGA&#xff0c;并在FPGA上实现逻辑解析&#xff0c;以点亮指定的小灯。…

Vim常用快捷键

这个是我的草稿本记录一下防止丢失&#xff0c;以后有时间进行整理 0 或功能键[Home]这是数字『 0 』&#xff1a;移动到这一行的最前面字符处 (常用)$ 或功能键[End]移动到这一行的最后面字符处(常用)G移动到这个档案的最后一行(常用)nGn 为数字。移动到这个档案的第 n 行。例…

【QT】QT背景介绍

本专栏内容为&#xff1a;QT学习专栏 通过本专栏的深入学习&#xff0c;你可以了解并掌握QT。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;QT &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&#x1f69a; &#x1f339;&#x1f…

灰度图恢复(C++)

思路&#xff0c;数字出现的次数与要统计的行列向匹配&#xff0c;函数表达式为 sum row*mcol 1; 例如初始出现次数为255 2&#xff0c;即255出现2次&#xff0c;则{0&#xff0c;0}、{0&#xff0c;1}都为255 #include <iostream> #include <sstream> #include…

3D分子生成的定制扩散框架 MolDiff - 评测

MolDiff模型是一种考虑分子键生成的3D分子生成的新模型。MolDiff是清华大学智能产业研究院马剑竹课题组发表在PMLR 2023的工作&#xff0c;第一作者是Xingang Peng&#xff0c;文章题目为&#xff1a;《 Addressing the Atom-Bond Inconsistency Problem in 3D Molecule Genera…

Rust中的链式调用方法

在Rust编程语言中&#xff0c;链式调用是一种流行的编程模式&#xff0c;它允许开发者以流畅、连续的方式调用多个方法。这种风格不仅提高了代码的可读性&#xff0c;而且使得复杂的操作可以串联在一起&#xff0c;形成一个清晰、简洁的语句。在Rust中&#xff0c;链式调用主要…

【Android】Kotlin学习之数据容器 -- 集合

一. 定义 List : 是一个有序列表, 可通过下标访问元素. 元素可以在list中出现多次, 元素可重复 Set : 是元素唯一的集合, 一般来说Set中元素的顺序并不重要, 无序集合. Map : 是一组键值对, 键是唯一的, 每个键刚好映射到一个值, 值可以重复 二. 集合创建 三. 示例 mutabl…

OSTE-Web-Log-Analyzer:基于Python的Web服务器日志自动化分析工具

关于OSTE-Web-Log-Analyzer OSTE-Web-Log-Analyzer是一款功能强大的Web服务器日志自动化分析工具&#xff0c;该工具专为安全研究人员设计&#xff0c;能够使用Python Web日志分析工具&#xff08;Python Web Log Analyzer&#xff09;帮助广大研究人员以自动化的形式实现Web服…

推导 模型矩阵的逆转置矩阵求运动物体的法向量

一个物体表面的法向量如何随着物体的坐标变换而改变&#xff0c;取决于变换的类型。使用逆转置矩阵&#xff0c;可以安全地解决该问题&#xff0c;而无须陷入过度复杂的计算中。 法向量变化规律 平移变换不会改变法向量&#xff0c;因为平移不会改变物体的方向。 旋转变换会改…

栈和队列的相互实现

1. 两个队列实现栈. - 力扣&#xff08;LeetCode&#xff09; 队列的特点是先进先出&#xff0c;而栈的特点是后进先出&#xff08;先进后出&#xff09;&#xff0c;也就是说重点在于利用两个队列来改变“出”的顺序。 假设我们在进行入栈操作的时候将数据依次入到一个队列中…

python如何单步调试

Python怎么单步调试&#xff1f;下面给大家介绍一下单步调试&#xff1a; 方法一&#xff1a;执行 python -m pdb myscript.py (Pdb) 会自己主动停在第一行。等待调试&#xff0c;这时你能够看看帮助。 方法二&#xff1a;在所调试程序的开头中&#xff1a;import pdb 并在你…