深入解析Python类中self的含义与用法:为什么使用self而不是其他名称
定义

首先,我们需要了解为什么Python类中使用self这个词,以及为什么不使用“zhangsan”和“lisi”这样的名称。这一定有它的目的。检查谷歌翻译的解释:
自己
名词定义:自我;自己;自己
那么问题来了,这里的自己指的是谁呢?下面就让我来详细分解一下吧。 (仅代表个人观点,如有错误,还请多多指教)
分析
测试代码基于此代码和其他扩展。我先发布代码。为了更好地理解,不要在不知道我在说什么的情况下长时间讲。
class A():
def song(one):
print(one)
def sing(self,one):
print(one)
1、首先要明白a=A()和a=A的区别。
a=A()
print(a)
a=A
print(a)
print(A)
结果如下:
<__main__.A object at 0x0000020A69C81780>
分析:
a=A() 是有地址的,这说明他是一个实体,比如 int a 中的 a 一样
a=A 是没有地址的,发现他和A打印的结果一毛一样,这说明他就是A,也就是一个类名,
等价于上一句中 int a 中的 int
那么也就是说下面这两语句是等价的
b=A() 与 b=a()
-------------------------------------------------------------------------
通过上面的分析,我们知道,a=A()相当于把 A 给实例化了,什么叫实例化呢,类比与 int a ,
int 什么都不能做,即 int 不能被赋值,不能进行算术操作等等,但是 a 可以(其实这里的 A 与 int
是一样的,追溯到C语言,类只不过是一种自定义的结构变量而已,只不过功能更加强大)。
那具体怎么个实例发呢?
2. self指的是谁?
class A():
def song(one):
print(one)
def sing(self,one):
print(one)
a=A()
A.sing(a,"hello") #注意这条语句
a.sing("hello")
打印结果:
hello
hello
-------------------------------
A.sing("hello")
错误信息:
TypeError: sing() missing 1 required positional argument: 'one'
提示没有给 one 赋值
--------------------------------
a.song("hello")
错误信息:
TypeError: song() takes 1 positional argument but 2 were given
那么问题来了,多给了一个什么参数,为什么会多给呢?
--------------------------------
把类A改一下
class A():
def song(one,two): #注意这里多给song了一个参数
print(one)
a.song("hello") //这里的参数 "hello"赋给了 two
print(a)
打印结果:
<__main__.A object at 0x0000020A69C39CC0>
<__main__.A object at 0x0000020A69C39CC0>
是不是很奇怪,为什么a.song("hello")返回的是 实例 a 的地址呢?
从这个例子可以发现,其实a.sing("hello")等价于A.sing(a, "hello"),而self就是实例a本身,如果找到self还可以使用其他词代替。
通过这个分析,我们简单知道类中的方法的第一个参数必须是self,否则实例无法正确调用类中的方法,即如果方法中的第一个参数不是self(广义上来说) sense) ,那么这个方法就没有任何价值,因为实例无法调用它。实在不知道无法调用的方法有什么用。
self 位于参数前面
x=6
class A():
def sing(self):
self.x=10
def mutl(self):
y=10*x
print(y)
a=A()
a.mutl()
我们先来猜猜结果。它会打印 60 还是 100?要弄清楚这个问题,首先要找出mutl()中的x是哪个,先看结果再分析。
结果是:60
为什么不在类内部调用 x 参数,而是在类外部调用 x 呢?还是同样的问题,self指的是谁?自我就是一个本身。那么问题就很明显了。 mutl()方法中x前面没有self,所以它调用的并不是实例(注意这里是实例,而不是类的参数)本身。
至此我想你大概明白了带 self 参数和不带 self 参数之间的区别了。简单来说,带self的参数属于实例本身,不带self的参数不管你爱谁。
不同方法中的参数可以互相使用吗?
class A():
def mutl(self):
x=5
def sing(self):
y=5*x
print(y)
a=A()
a.mutl()
a.sing()
错误如下:
in sing(self)
3 x=5
4 def sing(self):
----> 5 y=5*x
6 print(y)
7 # def print1(self):
NameError: name 'x' is not defined
可见参数前面不带self的参数只适用于本方法,不能跨方法调用。
class A():
def mutl(self):
self.x=5
def sing(self):
y=5*self.x
print(y)
a=A()
a.mutl()
a.sing()
打印结果:
25
这里可以清楚的看到没有报错,添加了self,立即实现了跨方法调用。
class A():
def mutl(self):
self.x=5
def sing(self):
y=5*self.x
print(y)
a=A()
a.sing()
首先想一下这段代码和上面的区别。
这里没有调用方法a.mutl()吗?结果如何?想一想。
in sing(self)
3 self.x=5
4 def sing(self):
----> 5 y=5*self.x
6 print(y)
7
AttributeError: 'A' object has no attribute 'x'
显示类中没有参数x。我是什么意思?我已经定义得很清楚了,对吧。但是实例化类之后,你并没有通过方法a.mutl()定义self.x。这就是为什么你首先需要有一个构造函数,并且只有在所有类中定义了所有参数后才能使用它。
概括
其实我说了这么多,也很混乱,但我只想解释两点:
仅当第一个参数为 self 时,类中的方法才能被实例调用。类中带self的参数都是instance,实例拥有这个参数的所有权,即实例中的所有方法都可以使用实例的参数。
至于什么时候在参数中添加self,什么时候不添加self,我想这个问题是不言自明的,只要你明白self扮演什么角色。
由于水平有限,分析可能存在一些错误。希望您不吝赐教并原谅我!