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_inputs
        self.training = is_training
        self.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 = name
        self.age = 0

五、重要说明

  • self 只是一个名字,你 technically 可以叫它 thismyself 或其他名字,但 强烈建议始终使用 self,这是 Python 社区的统一约定。

  • self 参数在调用方法时不需要手动传 ,Python 会自动传。

    复制代码
    p.greet()  # 正确,不需要写 p.greet(p)

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

回到神经网络代码

python 复制代码
dropout1, dropout2 = 0.2, 0.5

class 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_inputs
        self.training = is_training
        self.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))))
        # 只有在训练模型时才使用dropout
        if 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 out


net = Net(num_inputs, num_outputs, num_hiddens1, num_hiddens2)
  • self.lin1 表示:这个网络实例的第一个线性层。
  • self.relu 表示:这个网络实例的激活函数。
  • 每个 Net 实例都有自己的一套 lin1, lin2 等层,self 帮助区分和管理它们。

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

python 复制代码
self.num_inputs = num_inputs
self.training = is_training

但却没有定义

python 复制代码
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 是否在后续的函数或方法中需要调用该变量
相关推荐
gCode Teacher 格码致知13 小时前
Python基础教学:Python的openpyxl和python-docx模块结合Excel和Word模板进行数据写入-由Deepseek产生
python·excel
Destiny_where15 小时前
Agent平台-RAGFlow(2)-源码安装
python·ai
molunnnn16 小时前
第四章 Agent的几种经典范式
开发语言·python
linuxxx11017 小时前
django测试缓存命令的解读
python·缓存·django
毕设源码-邱学长18 小时前
【开题答辩全过程】以 基于Python的Bilibili平台数据分析与可视化实现为例,包含答辩的问题和答案
开发语言·python·数据分析
咚咚王者19 小时前
人工智能之编程进阶 Python高级:第十一章 过渡项目
开发语言·人工智能·python
A尘埃19 小时前
大模型应用python+Java后端+Vue前端的整合
java·前端·python
A尘埃19 小时前
LLM大模型评估攻略
开发语言·python
一晌小贪欢20 小时前
【Python办公】处理 CSV和Excel 文件操作指南
开发语言·python·excel·excel操作·python办公·csv操作