细说Js中的this

为什么使用this

先看个例子:

function identity() {
    return this.name.toUpperCase();
}

function speak() {
    return "Hello, i'm " + identity.call(this);
}

var me = {
    name: 'rod chen'
}

var you = {
    name: "others in Aug"
}

console.log(identity.call(me));  //ROD CHEN
console.log(identity.call(you)); //OTHERS IN AUG

console.log(speak.call(me));     //Hello, i'm ROD CHEN  
console.log(speak.call(you));    //Hello, i'm OTHERS IN AUG

输出的结果很明显,对于call的用法前面文章有提到,第一个参数就是传入到函数里的this的值。这段代码可以在不同的上下文对象( me 和 you )中重复使用函数 identify() 和 speak() ,如果我们不适用this的话,那就需要identity和speak显示传入一个上下文对象,就像下面的方式

function identity(context) {
    return context.name.toUpperCase();
}

function speak(context) {
    return "Hello, i'm " + identity(context);
}

var me = {
    name: 'rod chen'
}

var you = {
    name: "others in Aug"
}

console.log(identity(me));
console.log(identity(you));

console.log(speak(me));
console.log(speak(you));

总结:
this 提供了一种更优雅的方式来隐式“传递”一个对象引用,因此可以将API设计得更加简洁并且易于复用。随着使用模式越来越复杂,显式传递上下文对象会让代码变得越来越混乱,使用 this 则不会这样
​参考视频讲解:进入学习

Reference

ECMAScript 的类型分为语言类型和规范类型。

ECMAScript 语言类型是开发者直接使用 ECMAScript 可以操作的。其实就是我们常说的Undefined, Null, Boolean, String, Number, 和 Object。

而规范类型相当于 meta-values,是用来用算法描述 ECMAScript 语言结构和 ECMAScript 语言类型的。规范类型包括:Reference, List, Completion, Property Descriptor, Property Identifier, Lexical Environment, 和 Environment Record。

没懂?没关系,我们只要知道在 ECMAScript 规范中还有一种只存在于规范中的类型,它们的作用是用来描述语言底层行为逻辑。

Reference 类型就是用来解释诸如 delete、typeof 以及赋值等操作行为的

这里的 Reference 是一个 Specification Type,也就是 “只存在于规范里的抽象类型”。它们是为了更好地描述语言的底层行为逻辑才存在的,但并不存在于实际的 js 代码中。

组成

这段讲述了 Reference 的构成,由三个组成部分,分别是:

  • base value
  • referenced name
  • strict reference

可是这些到底是什么呢?

我们简单的理解的话:

base value 就是属性所在的对象或者就是 EnvironmentRecord,它的值只可能是 undefined, an Object, a Boolean, a String, a Number, or an environment record 其中的一种。

referenced name 就是属性的名称。

var foo = 1;

// 对应的Reference是:
var fooReference = {
    base: EnvironmentRecord,
    name: 'foo',
    strict: false
};
var foo = {
    bar: function () {
        return this;
    }
};

foo.bar(); // foo

// bar对应的Reference是:
var BarReference = {
    base: foo,
    propertyName: 'bar',
    strict: false
};

方法

  • GetBase:返回 reference 的 base value。
  • IsPropertyReference:简单的理解:如果 base value 是一个对象,就返回true。
  • GetValue:返回具体的值

如何确定this的值

function call步骤
  1. 令 ref 为解释执行 MemberExpression 的结果 .
  2. 令 func 为 GetValue(ref).
  3. 令 argList 为解释执行 Arguments 的结果 , 产生参数值们的内部列表 (see 11.2.4).
  4. 如果 Type(func) is not Object ,抛出一个 TypeError 异常 .
  5. 如果 IsCallable(func) is false ,抛出一个 TypeError 异常 .
  6. 如果 Type(ref) 为 Reference,那么 如果 IsPropertyReference(ref) 为 true,那么 令 thisValue 为 GetBase(ref). 否则 , ref 的基值是一个环境记录项 令 thisValue 为调用 GetBase(ref) 的 ImplicitThisValue 具体方法的结果
  7. 否则 , 假如 Type(ref) 不是 Reference. 令 thisValue 为 undefined.
  8. 返回调用 func 的 [[Call]] 内置方法的结果 , 传入 thisValue 作为 this 值和列表 argList 作为参数列表
MemberExpression
  • PrimaryExpression // 原始表达式 可以参见《JavaScript权威指南第四章》
  • FunctionExpression // 函数定义表达式
  • MemberExpression [ Expression ] // 属性访问表达式
  • MemberExpression . IdentifierName // 属性访问表达式
  • new MemberExpression Arguments // 对象创建表达式

这里说的是方法调用的左边部分。

function foo() {
    console.log(this)
}

foo(); // MemberExpression 是 foo

function foo() {
    return function() {
        console.log(this)
    }
}

foo()(); // MemberExpression 是 foo()

var foo = {
    bar: function () {
        return this;
    }
}

foo.bar(); // MemberExpression 是 foo.bar
判断ref的类型

第一步计算ref,第七步需要判断ref是不是一个reference类型。

var value = 1;

var foo = {
  value: 2,
  bar: function () {
    return this.value;
  }
}

//示例1
console.log(foo.bar());
//示例2
console.log((foo.bar)());
//示例3
console.log((foo.bar = foo.bar)());
//示例4
console.log((false || foo.bar)());
//示例5
console.log((foo.bar, foo.bar)());

foo.bar()
这个是属性访问。根据11.2.1 property accessors最后一步:

Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict.

返回了一个reference类型:返回一个reference类型的引用,其基值为 baseValue 且其引用名为 propertyNameString, 严格模式标记为 strict

var Reference = {
  base: foo,
  name: 'bar',
  strict: false
};

然后回到[function call](function call)第六、七步,

  • 如果 Type(ref) 为 Reference,那么 如果 IsPropertyReference(ref) 为 true,那么 令 thisValue 为 GetBase(ref). 否则 , ref 的基值是一个环境记录项 令 thisValue 为调用 GetBase(ref) 的 ImplicitThisValue 具体方法的结果
  • 否则 , 假如 Type(ref) 不是 Reference. 令 thisValue 为 undefined.

这里因为foo是一个对象,所以这里IsPropertyReference(ref) 的值为true。所以这里this的值就是GetBase(ref)就是foo。

(foo.bar)()
分组表达式规则如下:

  1. 返回执行Expression的结果,它可能是Reference类型

这里的结果和上面相同都是fo。

(foo.bar = foo.bar)()
涉及到简单赋值,规则如下:

  1. 令 lref 为解释执行 LeftH 和 SideExpression 的结果 .
  2. 令 rref 为解释执行 AssignmentExpression 的结果 .
  3. 令 rval 为 GetValue(rref).
  4. 抛出一个 SyntaxError 异常,当以下条件都成立 :
    • Type(lref) 为 Reference
    • IsStrictReference(lref) 为 true
    • Type(GetBase(lref)) 为环境记录项
    • GetReferencedName(lref) 为 “eval” 或 “arguments”
  5. 调用 PutValue(lref, rval).
  6. 返回 rval.

这里的返回值为第三部,GetValue。这是一个具体的返回值。根据上面的值,得到this的值为undefined,非严格模式下这里隐式装换为window对象。

(false || foo.bar)()和(foo.bar, foo.bar)()
这里的返回值都是去的getValue的值。所以this都和上面一样。

看一下最终的结果:

var value = 1;

var foo = {
  value: 2,
  bar: function () {
    return this.value;
  }
}

//示例1
console.log(foo.bar()); // 2
//示例2
console.log((foo.bar)()); // 2
//示例3
console.log((foo.bar = foo.bar)()); // 1
//示例4
console.log((false || foo.bar)()); // 1
//示例5
console.log((foo.bar, foo.bar)()); // 1

普通函数
function foo() {
    console.log(this)
}

foo(); 

这种属于解析标识符

The result of evaluating an identifier is always a value of type Reference with its referenced name component equal to the Identifier String.

解释执行一个标识符得到的结果必定是 引用 类型的对象,且其引用名属性的值与 Identifier 字符串相等。

那么baseValue是什么值呢?因为解析标识符会调用的结果是GetIdentifierReference。

  1. 如果 lex 的值为 null,则:
    1. 返回一个类型为 引用 的对象,其基值为 undefined,引用的名称为 name,严格模式标识的值为 strict。
  2. 令 envRec 为 lex 的环境数据。
  3. 以 name 为参数 N,调用 envRec 的 HasBinding(N) 具体方法,并令 exists 为调用的结果。
  4. 如果 exists 为 true,则:
    1. 返回一个类型为 引用 的对象,其基值为 envRec,引用的名称为 name,严格模式标识的值为 strict。
  5. 否则:
    1. 令 outer 为 lex 的 外部环境引用 。
    2. 以 outer、name 和 struct 为参数,调用 GetIdentifierReference,并返回调用的结果。

这里因为是window对象所以这里返回的是:

var fooReference = {
    base: EnvironmentRecord,  // 或许这里是undefined
    name: 'foo',
    strict: false
};

不管base的值是上面两种的哪一种,那都不是Object。那根据上面的规则:

  • 如果 Type(ref) 为 Reference,那么 如果 IsPropertyReference(ref) 为 true,那么 令 thisValue 为 GetBase(ref). 否则 , ref 的基值是一个环境记录项 令 thisValue 为调用 GetBase(ref) 的 ImplicitThisValue 具体方法的结果
  • 否则 , 假如 Type(ref) 不是 Reference. 令 thisValue 为 undefined.

this的值为ImplicitThisValue的值。这个值返回的一直undefined。所以这里this的是undefined。

什么是this

说的是执行上下文的thisbinding。
this说的是当前函数的调用位置。这个是概念描述。下面通过上面的只是去分析各种情况下的thisbinding是什么东西。

this 提供了一种更优雅的方式来隐式“传递”一个对象引用,因此可以将API设计得更加简洁
并且易于复用。随着使用模式越来越复杂,显式传递上下文对象会让代码变得越来越混乱,使用 this 则不会这样

函数调用

具体参照上面说的普通函数

call,apply

var person = {
  name: "axuebin",
  age: 25
};
function say(job){
  console.log(this.name+":"+this.age+" "+job);
}
say.call(person,"FE"); // axuebin:25
say.apply(person,["FE"]); // axuebin:25
call

Function.prototype.call (thisArg [ , arg1 [ , arg2, … ] ] ) 当以 thisArg 和可选的 arg1, arg2 等等作为参数在一个 func 对象上调用 call 方法,采用如下步骤:

  1. 如果 IsCallable(func) 是 false, 则抛出一个 TypeError 异常。
  2. 令 argList 为一个空列表。
  3. 如果调用这个方法的参数多余一个,则从 arg1 开始以从左到右的顺序将每个参数插入为 argList 的最后一个元素。
  4. 提供 thisArg 作为 this 值并以 argList 作为参数列表,调用 func 的 [[Call]] 内部方法,返回结果。

call 方法的 length 属性是 1。

this的值为传入thisArg的值。

apply
  1. 如果IsCallable(func) 是 false, 则抛出一个 TypeError 异常
  2. 如果 argArray 是 null 或 undefined, 则
    1. 返回提供 thisArg 作为 this 值并以空参数列表调用 func 的 [[Call]] 内部方法的结果。
  3. 如果 Type(argArray) 不是 Object, 则抛出一个 TypeError 异常 .
  4. 令 len 为以 “length” 作为参数调用 argArray 的 [[Get]] 内部方法的结果。
  5. 令 n 为 ToUint32(len).
  6. 令 argList 为一个空列表 .
  7. 令 index 为 0.
  8. 只要 index < n 就重复
    1. 令 indexName 为 ToString(index).
    2. 令 nextArg 为以 indexName 作为参数调用 argArray 的 [[Get]] 内部方法的结果。
    3. 将 nextArg 作为最后一个元素插入到 argList 里。
    4. 设定 index 为 index + 1.
  9. 提供 thisArg 作为 this 值并以 argList 作为参数列表,调用 func 的 [[Call]] 内部方法,返回结果。

apply 方法的 length 属性是 2。

注意  在外面传入的 thisArg 值会修改并成为 this 值。thisArg 是 undefined 或 null 时它会被替换成全局对象,所有其他值会被应用 ToObject 并将结果作为 this 值,这是第三版引入的更改。

function [[call]]

因为上面说了调用function的[[Call]]内部方法。
当用一个 this 值,一个参数列表调用函数对象 F 的 [[Call]] 内部方法,采用以下步骤:

  1. 用 F 的 [[FormalParameters]] 内部属性值,参数列表 args,10.4.3 描述的 this 值来建立 函数代码 的一个新执行环境,令 funcCtx 为其结果。
  2. 令 result 为 FunctionBody(也就是 F 的 [[Code]] 内部属性)解释执行的结果。如果 F 没有 [[Code]] 内部属性或其值是空的 FunctionBody,则 result 是 (normal, undefined, empty)。
  3. 退出 funcCtx 执行环境,恢复到之前的执行环境。
  4. 如果 result.type 是 throw 则抛出 result.value。
  5. 如果 result.type 是 return 则返回 result.value。
  6. 否则 result.type 必定是 normal。返回 undefined。

这里又提到了10.4.3的执行函数代码的规则:

当控制流根据一个函数对象 F、调用者提供的 thisArg 以及调用者提供的 argumentList,进入 函数代码 的执行环境时,执行以下步骤:

  1. 如果 函数代码 是 严格模式下的代码 ,设 this 绑定为 thisArg。
  2. 否则如果 thisArg 是 null 或 undefined,则设 this 绑定为 全局对象 。
  3. 否则如果 Type(thisArg) 的结果不为 Object,则设 this 绑定为 ToObject(thisArg)。
  4. 否则设 this 绑定为 thisArg。
  5. 以 F 的 [[Scope]] 内部属性为参数调用 NewDeclarativeEnvironment,并令 localEnv 为调用的结果。
  6. 设词法环境为 localEnv。
  7. 设变量环境为 localEnv。
  8. 令 code 为 F 的 [[Code]] 内部属性的值。
  9. 10.5 描述的方案,使用 函数代码 code 和 argumentList 执行定义绑定初始化步骤。

bind

var person = {
  name: "axuebin",
  age: 25
};
function say(){
  console.log(this.name+":"+this.age);
}
var f = say.bind(person);
console.log(f());

里面同样的也是讲传入的thisArg设置this的值。

箭头函数

箭头函数并不绑定 this,arguments,super(ES6),或者 new.target(ES6),这些知识沿用包含当前箭头函数的封闭的词法环境。

function foo() {
   setTimeout( () => {
      console.log("args:", arguments);
   },100);
}

foo( 2, 4, 6, 8 );
// args: [2, 4, 6, 8]
说法定义纠正
  1. 箭头函数的this是绑定到父函数foo的,其实不是,只是沿用。因为箭头函数内部没有做任何的绑定操作。
  2. 局部变量this 下面的例子是为了说明局部变量this
function foo() {
   var self = this;
   setTimeout(function() {
      console.log("id:" + this.id);
   },100);
}

foo.call( { id: 42 } );
// id:undefined

这里为什么是undefined,因为这里setTimeout是windows对象的属性。this指向window。

然后修改了一下:

function foo() {
   var self = this;
   setTimeout(function() {
      console.log("id:" + self.id);
   },100);
}

foo.call( { id: 42 } );
// id:42

这里是因为self对于function的执行是一个执行上下文变量环境outer指向的包含当前函数的闭合函数变量环境。这里和this没有任何关系。

这里提一下:“因为 this 无论如何都是局部的”。this都是函数执行的this绑定规则来决定的。

作为对象的一个方法

参照:上文foo.bar函数调用的解析

作为一个构造函数

[[construct]]

  1. 令 obj 为新创建的 ECMAScript 原生对象。
  2. 依照 8.12 设定 obj 的所有内部方法。
  3. 设定 obj 的 [[Class]] 内部方法为 “Object”。
  4. 设定 obj 的 [[Extensible]] 内部方法为 true。
  5. 令 proto 为以参数 “prototype” 调用 F 的 [[Get]] 内部属性的值。
  6. 如果 Type(proto) 是 Object,设定 obj 的 [[Prototype]] 内部属性为 proto。
  7. 如果 Type(proto) 不是 Object,设定 obj 的 [[Prototype]] 内部属性为 15.2.4 描述的标准内置的 Object 的 prototype 对象。
  8. 以 obj 为 this 值,调用 [[Construct]] 的参数列表为 args,调用 F 的 [[Call]] 内部属性,令 result 为调用结果。
  9. 如果 Type(result) 是 Object,则返回 result。
  10. 返回 obj

我们可以看到this绑定在当前创建的对象。

作为一个DOM事件处理函数

this指向触发事件的元素,也就是始事件处理程序所绑定到的DOM节点。

var ele = document.getElementById("id");
ele.addEventListener("click",function(e){
  console.log(this);
  console.log(this === e.target); // true
})

这里可能不太好知道。从文献中了解到:

The event listener is appended to target’s event listener list

interface EventTarget {
  constructor();

  undefined addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options = {});
  undefined removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options = {});
  boolean dispatchEvent(Event event);
};

callback interface EventListener {
  undefined handleEvent(Event event);
};

dictionary EventListenerOptions {
  boolean capture = false;
};

dictionary AddEventListenerOptions : EventListenerOptions {
  boolean passive = false;
  boolean once = false;
};

根据EventTarget的属性,可以看到callback是一级属性,所以Event.callback的执行的this指向的是EventTarget。当然具体的实现没有看到

从侧面了解:还有一种写法:button.onclick = foo。这种就可以很好的了解了。

this优先级

现在我们可以根据优先级来判断函数在某个调用位置应用的是哪条规则。可以按照下面的顺序来进行判断:

  1. 函数是否在 new 中调用( new 绑定)?如果是的话 this 绑定的是新创建的对象。
var bar = new foo()
  1. 函数是否通过 call 、 apply (显式绑定)或者硬绑定调用?如果是的话, this 绑定的是指定的对象。
var bar = foo.call(obj2)
  1. 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话, this 绑定的是那个上下文对象。
var bar = obj1.foo()
  1. 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined ,否则绑定到全局对象。
var bar = foo()

结论:new 调用 > call、apply、bind 调用 > 对象上的函数调用 > 普通函数调用

// 例子来源:若风 https://juejin.cn/post/6844903746984476686#heading-12
var name = 'window';
var person = {
    name: 'person',
}
var doSth = function(){
    console.log(this.name);
    return function(){
        console.log('return:', this.name);
    }
}
var Student = {
    name: 'rod',
    doSth: doSth,
}
// 普通函数调用
doSth(); // window
// 对象上的函数调用
Student.doSth(); // 'rod'
// call、apply 调用
Student.doSth.call(person); // 'person'
new Student.doSth.call(person); // Uncaught TypeError: Student.doSth.call is not a constructor

最后这一行说一下,因为. 运算符的优先级高于new。所以这里是Student.doSth.call作为new的构造函数。但是因为call的方法执行的时候,执行的是func的[[call]]方法。想要吊用new的话需要调用[[Construct]] 属性

call的调用

当以 thisArg 和可选的 arg1, arg2 等等作为参数在一个 func 对象上调用 call 方法,采用如下步骤:

  1. 如果 IsCallable(func) 是 false, 则抛出一个 TypeError 异常。
  2. 令 argList 为一个空列表。
  3. 如果调用这个方法的参数多余一个,则从 arg1 开始以从左到右的顺序将每个参数插入为 argList 的最后一个元素。
  4. 提供 thisArg 作为 this 值并以 argList 作为参数列表,调用 func 的 [[Call]] 内部方法,返回结果。
<think>好的,我现在需要帮助用户理解强化学习中的“episodes”具体含义和用法。首先,我要回顾一下强化学习的基本概念,确保自己对episode的理解准确。记得在强化学习中,agent与环境交互,通过试错来学习策略,而episode可能是指一个完整的学习周期。 首先,我应该明确episode的定义。在强化学习中,episode通常指的是一次从初始状态到终止状态的完整交互过程。比如在游戏中,一局游戏从开始到结束就是一个episode。每个episode包含多个时间步,agent在每个时间步做出动作,环境返回新的状态和奖励。当达到终止状态时,当前episode结束,可能重新开始新的episode。 接下来,我需要思考episode的结构。比如,每个episode有开始和结束,终止条件可能包括任务完成、失败或达到最大步数。在回合制任务中,如棋类游戏或迷宫导航,episode结构比较明显。而在持续任务中,比如自动驾驶,可能没有明确的终止,这时候可能需要人为设定episode的划分,比如按时间块来分。 然后是关于episode在训练中的作用。比如,在基于episode的算法中,如蒙特卡洛方法,需要完整的episode数据来更新策略。而时序差分方法如Q-learning可以在每个时间步更新,但episode仍然用于评估整体表现。经验回放机制中,episode的数据可能被存储并随机采样,以打破数据间的相关性,提高训练稳定性。 应用场景方面,回合制任务如游戏、广告投放优化、机器人任务训练等会用到episode。而持续任务可能需要不同的处理方式,比如将长时间运行的任务分成多个episode来训练。此外,多智能体强化学习中,episode的结构可能更复杂,需要协调多个agent的交互周期。 用户可能还想知道如何设置episode的长度,以及不同设置对训练的影响。比如,过短的episode可能无法让agent学到长期策略,而过长则可能导致训练效率低下。此外,在元学习或Few-Shot Learning中,episode可能用于模拟不同的任务场景,帮助模型快速适应新环境。 需要引用提供的参考文献来支持回答。比如引用[1]提到强化学习的基本概念,引用[4]提到元学习和Few-Shot Learning中使用的工具如Meta-World,这可能与episode在任务划分中的应用有关。同时,引用[3]讨论多智能体场景中的episode结构可能更复杂。 最后,确保回答结构清晰,分点解释episode的含义、结构、训练中的作用和应用场景,并生成相关问题。同时,检查是否所有数学表达式正确使用$...$或$$...$$格式,比如提到累积奖励时使用$G_t = \sum_{k=0}^{T} \gamma^k r_{t+k}$这样的公式,确保符合格式要求。</think>### 强化学习中 Episodes 的详细解释及应用场景 #### 1. Episode 的基本含义 在强化学习中,**Episode(回合)** 表示智能体与环境从初始状态到终止状态的完整交互过程。例如,在游戏中,一局游戏从开始到结束即为一个 Episode,包含多个时间步(Time Step)。每个时间步中,智能体根据当前状态 $s_t$ 选择动作 $a_t$,环境反馈奖励 $r_t$ 并转移到新状态 $s_{t+1}$。当达到终止条件(如任务成功/失败或达到最大步数)时,Episode 结束[^1]。 #### 2. Episode 的结构与终止条件 - **典型结构**: $$s_0 \xrightarrow{a_0, r_0} s_1 \xrightarrow{a_1, r_1} s_2 \xrightarrow{} \cdots \xrightarrow{} s_T$$ 其中 $s_T$ 为终止状态。 - **终止条件**: - 任务完成(如机器人到达目标) - 任务失败(如游戏角色死亡) - 达到预设的最大步数(防止无限循环) #### 3. Episode 在训练中的作用 - **数据收集**:每个 Episode 提供完整的轨迹数据,用于策略更新。例如,蒙特卡洛方法(Monte Carlo)需通过完整 Episode 计算累积奖励 $G_t = \sum_{k=0}^{T} \gamma^k r_{t+k}$,其中 $\gamma$ 为折扣因子[^1]。 - **性能评估**:通过多个 Episode 的平均回报衡量策略优劣。 - **经验回放**:存储不同 Episode 的交互数据,打破时间相关性,提升训练稳定性[^4]。 #### 4. Episode 的应用场景 1. **回合制任务** - **游戏场景**:如 AlphaGo 的每局围棋对弈为一个 Episode。 - **广告投放优化**:以用户一次完整会话(点击、浏览、购买)为一个 Episode。 - **机器人任务**:如机械臂完成一次抓取动作的周期。 2. **持续任务的分段处理** 对于无明确终止的持续任务(如自动驾驶),常将长时间运行的任务划分为多个 Episode,例如按固定时间间隔或事件触发重置环境[^3]。 3. **元学习与 Few-Shot Learning** 在元学习中,每个 Episode 对应一个子任务(如不同迷宫布局),帮助模型快速适应新环境[^4]。 #### 5. 代码示例 ```python # 强化学习训练循环中的 Episode 控制 for episode in range(total_episodes): state = env.reset() done = False while not done: action = agent.choose_action(state) next_state, reward, done, _ = env.step(action) agent.update(state, action, reward, next_state, done) state = next_state agent.finalize_episode() # 更新策略或评估性能 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值