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

Python类(class)参数self的理解

问题

在python类中,经常可以看见self参数,比如:

class Net(nn.Module):def __init__(self, num_inputs, num_outputs, num_hiddens1, num_hiddens2,is_training=True):super().__init__()self.num_inputs = num_inputsself.training = is_trainingself.lin1 = nn.Linear(num_inputs, num_hiddens1)self.lin2 = nn.Linear(num_hiddens1, num_hiddens2)self.lin3 = nn.Linear(num_hiddens2, num_outputs)self.relu = nn.ReLU()

那么这个参数该如何理解呢?

self 是 Python 类(class)中最核心、最关键的概念之一。理解 self 对于掌握面向对象编程至关重要。


一、self 是什么?

self 是一个约定俗成的名称,它代表类的(实例)

  • 每当你创建一个类的实例(对象),Python 会自动把这个实例作为第一个参数传递给类中的方法。
  • self 就是用来接收这个“实例本身”的参数。

二、举个例子来理解

class Person:def __init__(self, name):self.name = name  # 把传入的 name 保存到这个实例中def greet(self):print(f"Hello, I am {self.name}")# 创建一个实例
p = Person("Alice")
p.greet()  # 输出:Hello, I am Alice

我们来一步步分析:

  1. p = Person("Alice")

    • 创建了一个 Person 类的实例,叫 p
    • Python 自动调用 __init__ 方法,并把 p 这个实例作为第一个参数传进去。
    • 所以在 __init__ 中,self 就是 p
    • self.name = name 相当于 p.name = "Alice"
  2. p.greet()

    • 调用 greet 方法。
    • Python 自动把 p 作为第一个参数传给 greet 方法。
    • 所以在 greet 中,self 也是 p
    • self.name 就是 p.name,也就是 "Alice"

三、为什么需要 self

因为一个类可以创建多个实例,每个实例有自己的数据。self 让每个方法都知道“我现在操作的是哪一个实例”。

p1 = Person("Alice")
p2 = Person("Bob")p1.greet()  # Hello, I am Alice
p2.greet()  # Hello, I am Bob

虽然 p1p2 都调用同一个 greet 方法,但 self 不同,所以访问的数据也不同。


四、self 在哪里出现?

  1. 定义方法时:必须把 self 作为第一个参数。

    def greet(self):...
  2. 访问实例变量或调用其他方法时:用 self.xxx

    self.name = "Alice"
    self.greet()
  3. __init__ 中初始化属性

    def __init__(self, name):self.name = nameself.age = 0

五、重要说明

  • self 只是一个名字,你 technically 可以叫它 thismyself 或其他名字,但 强烈建议始终使用 self,这是 Python 社区的统一约定。
  • self 参数在调用方法时不需要手动传,Python 会自动传。
    p.greet()  # 正确,不需要写 p.greet(p)

六、什么是需要self.param = param

回到神经网络代码

dropout1, dropout2 = 0.2, 0.5class Net(nn.Module):def __init__(self, num_inputs, num_outputs, num_hiddens1, num_hiddens2,is_training = True):super(Net, self).__init__()self.num_inputs = num_inputsself.training = is_trainingself.lin1 = nn.Linear(num_inputs, num_hiddens1)self.lin2 = nn.Linear(num_hiddens1, num_hiddens2)self.lin3 = nn.Linear(num_hiddens2, num_outputs)self.relu = nn.ReLU()def forward(self, X):H1 = self.relu(self.lin1(X.reshape((-1, self.num_inputs))))# 只有在训练模型时才使用dropoutif self.training == True:# 在第一个全连接层之后添加一个dropout层H1 = dropout_layer(H1, dropout1)H2 = self.relu(self.lin2(H1))if self.training == True:# 在第二个全连接层之后添加一个dropout层H2 = dropout_layer(H2, dropout2)out = self.lin3(H2)return outnet = Net(num_inputs, num_outputs, num_hiddens1, num_hiddens2)
  • self.lin1 表示:这个网络实例的第一个线性层。
  • self.relu 表示:这个网络实例的激活函数。
  • 每个 Net 实例都有自己的一套 lin1lin2 等层,self 帮助区分和管理它们。

一个问题,对于实例中的参数,为什么这里定义了

self.num_inputs = num_inputs
self.training = is_training

但却没有定义 

self.num_outputs = num_inputs
self.num_hiddens1 = num_hiddens1

即为什么有些参数被保存为实例变量,而有些没有?

答案核心:是否需要在类的其他方法中使用这些参数

在 Python 类中,是否将某个变量保存为 self.xxx,取决于你是否希望在类的其他方法中访问它。

可以看到,在后续的def forward()中,调用了self.num_inputs、self.training,而没有调用到num_outputsnum_hiddens1


总结

概念说明
self代表当前类的实例(对象)
作用让方法可以访问和修改实例的数据
出现位置方法定义的第一个参数,访问属性/方法时用 self.xxx
是否手动传否,Python 自动传
为什么重要实现“一个类,多个实例,各自独立”
什么时候需要self.param=param是否在后续的函数或方法中需要调用该变量

http://www.lryc.cn/news/601629.html

相关文章:

  • ROS2总结(二)
  • VMware Workstation Pro虚拟机的下载和安装图文保姆级教程(附下载链接)
  • Mysql 二进制安装常见问题
  • QUARTUS速通流程
  • HCIP---MGRE实验
  • 数学建模——模糊综合评价
  • 2-4、Dify案例实践—基于工作流构建商城用户评价智能分析系统
  • 算法竞赛阶段二-数据结构(37)数据结构循环链表模拟实现
  • print(“\033[31m红\033[32m绿\033[34m蓝\033[0m默认色“)
  • 零基础学习性能测试第五章:JVM性能分析与调优-JVM运行时内存区域介绍
  • Maven之多模块项目管理
  • C语言——关于指针(逐渐清晰版)
  • 嵌入式——单片机的独立按键
  • 数据结构基础内容(第七篇:堆、哈夫曼树)
  • 电子电气架构 --- 软件bug的管理模式
  • 「iOS」————MRC
  • Flink2.0学习笔记:Stream API 常用转换算子
  • 第十八章:AI的“通感”:揭秘图、文、音的共同语言——CLIP模型
  • 常见认证机制详解
  • Unity FXAA
  • 设计模式(六)创建型:单例模式详解
  • 五、搭建springCloudAlibaba2021.1版本分布式微服务-gateway网关
  • 新手开发 App,容易陷入哪些误区?
  • c++加载qml文件
  • 【学习笔记】DexMimicGen:通过模仿学习实现双臂灵巧操作的自动化数据生成
  • 小白成长之路-Ansible自动化(一)
  • 小白投资理财 - 从换手率和成交量分析股票趋势
  • 【机器学习深度学习】NLP评价指标 BLEU 和 ROUGE
  • 扩展组件(uni-ui)之uni-group
  • Dify 本地化部署深度解析与实战指南