1. 前言
我们总会在class里面看见self,但是感觉他好像也没什么用处,就是放在那里占个位子。
如果你也有同样的疑问,那么恭喜你,你的class没学明白。
所以,在解释self是谁之前,我们先明确几个问题:
- 什么是class,什么是instance,什么是object?
- 什么是method,什么是function?
1.1 什么是class,什么是instance,什么是object?
Class: 可以理解为一个组装工厂。假如我们要生产一个机器人,那我们先要搭个工厂吧。先确定:我们要先安装胳膊,再安装头,我们的小破机器人的流水线就搭好了。这个工厂比较智能,胳膊和头的数量都可以调。
class BuildRobot():
def __init__(self,armcount,headcount):
self.armcount = armcount
self.headcount = headcount
所以这里的class,就是搭了一个工厂叫BuildRobot。'__init__' 就是告诉这个流水线,首先你需要这个机器人有几个胳膊(‘armcount’),有几个脑袋(‘headcount’)。先忽略一下这里的self,以后讲。
这个时候你可以run一下,这样你的class就搭好了。可是这时的工厂,因为你没有开始生产,是没有任何产出的。下面就是instance:
instance:可以理解为启动一次工厂生产出的机器人。现在我们用之前搭的工厂生产一个正常一点的机器人,两个胳膊一个脑袋:
normal_robot = BuildRobot(2,1)
查看一下胳膊数对不对?
normal_robot.armcount
# 2
我们再来一个 不太正常的机器人:
weird_robot = BuildRobot(4,1)
normal_robot 和weird_robot 都是instance。他们虽然胳膊数量不一样,但是本质上都是由这个class造出来的,由胳膊和头组成的机器人。
object: 这个就比较麻烦了,大部分情况下,object和instance的含义是一样的,都是指这个造出来的robot。这两者的区别,只是在英语语言环境下的区别:
- normal_robot is an instance of 'buildrobot'
- normal_robot is a 'buildrobot' object
1.2 什么是method,什么是function?
两者都由def定义,稍微粗糙一点的理解就是,在class里面的function叫method。所以,method是和class,instance有关的一种function。
举个栗子:
还是上面的工厂,我们现在加装一个车间,负责把胳膊上色:
class BuildRobot():
def __init__(self,armcount,headcount):
self.armcount = armcount
self.headcount = headcount
def paintarm(self,color):
print("paint arm:",color)
这个paintarm,就是一个method。还是一样,现在这个class没有生产,因此这个method也没有任何实际的产品出来。我们只能先生产出一个instance来:
colorful_robot = BuildRobot(2,1)
好的我们现在有一个两个胳膊一个头的robot了。这时,我们的robot还是没有上色的,因为我们没有让这个instance进入上色的那个车间。现在我们让这个robot进入车间,涂个红色。
colorful_robot.paintarm('red')
# paint arm: red
上面的过程,就是call这个paintarm method。几个点:
- 如果没有先造一个机器人,这个车间就没有办法给胳膊上色,因此要上色,就必须先造一个机器人出来。所以,method是依赖于instance的。
- 这个车间只能给这个工厂产出的robot的胳膊上色,你从别的工厂拿一个车过来让他上色,他是不干的。因此,method是依赖于class的。只有这个class创建的instance,才能call这个method。
假如我把上色这个活,外包了。我就在外面另建了个工厂,专门上色,这就是function:
def outsourcing_paint(robot,color):
print("paint",robot,"arm:",color)
outsourcing_paint(colorful_robot,‘red’)
# paint <main.BuildRobot object at 0x116b434a8> arm: red
这个外包的上色工厂,不管你这个东西是从哪个工厂来的,无论你是个机器人还是机器狗,反正我就拿来,给胳膊上色。
看到这里,应该就明白function和method的区别了。
注意method其实有两种,一种是instance method,一种是class method。
- instance method就相当于对于机器人这个产品进行各种修改的车间。我给机器人上色,不影响我这个工厂的外形对吧?
- class method,是对这个工厂,这个class的属性进行修改的车间,比如我有一个车间负责把工厂涂成红色的。这个行为并不影响我造出来的机器人的大小颜色属性。
2. self详细解析
2.1 神奇的self
在Python类中规定,函数的第一个参数是实例对象本身,并且约定俗成,把其名字写为self。其作用相当于java中的this,表示当前类的对象,可以调用当前类中的属性和方法。
class是面向对象的设计思想,instance(也即是 object,对象)是根据 class 创建的。
一个类(class)应该包含数据和操作数据的方法,通俗来讲就是 属性 和 函数(即调用方法)。
2.2 类 class 中为啥用使用 self ?
在类的代码(函数)中,需要访问当前的实例中的变量和函数,即,访问Instance中的:
- 对应的变量(property):Instance.ProperyNam,去读取之前的值和写入新的值。
- 调用对应函数(function):Instance.function(),即执行对应的动作。
而需要访问实例的变量和调用实例的函数,当然需要对应的实例Instance对象本身。而Python中就规定好了,函数的第一个参数,就必须是实例对象本身,并且建议,约定俗成,把其名字写为self。所以,我们需要self(需要用到self)。
首先,在Python中类的定义:
class 后面紧跟 类名,即 Person,类名通常大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的,通常,如果没有合适的 继承类,就使用 object 类,这是所有类最终都会 继承的类。
在python中,类是通过关键字 class 定义的:
class Person(object):
pass
将 Person类实例化,创建实例化是通过 类名() 实现的。
class Person(object):
pass
student = Person() # 创建类的实例化
print(student)
print(Person)
输出结果:
<main.Person object at 0x0000019875279DA0>
<class ‘main.Person’>
可以看到,变量 student指向的就是一个 Person的 object,后面的 0x0000026EE434D8D0 是内存地址,每个 object 的地址都不一样,而 Person 本身则是一个 类。
也可以给实例变量绑定属性,比如:为 student 绑定 name 和 score 属性:
class Person(object):
pass
student = Person()
# print(student)
# print(Person)
student.name = “Gavin” # 为实例变量 student 绑定 name 属性 类似于 赋值 操作
student.score = 100 # 为 其绑定 score 属性
print(student.name)
print(student.score)
输出结果:
Gavin
100
上述的方法虽然可以为类的实例变量绑定属性,但是不够方便和elegant , 由于类 可以起到模板的作用,故在创建实例的时候,可以将我们认为必须绑定 属性 强制填写进去,在 python中,是通过 类中通常都会使用的一个方法,即def init(self) 方法,在创建实例变量的时候,就把 name 和 score 等属性绑上去。
class Person(object):
def init(self,name,score):
self.name = name
self.score = score
student = Person(‘Gavin’,100) # 传入 init 方法中需要的 参数
print(student.name)
print(student.score)
输出结果:
Gavin
100
传入空参数的情况,会报错:
student = Person() # 此处应该有参数传入,却没有传
报错类型:
TypeError: init() missing 2 required positional arguments: ‘name’ and 'score’
注意:
- init 方法的第一个参数永远是 self ,表示创建的实例本身,因此,在 init 方法的内部,就可以把各种属性绑定到 self,因为 self 就指向创建的 实例本身。
- 使用了 init 方法,在创建实例的时候就不能传入 空的参数了,必须传入与 init 方法匹配的参数,但是 self 不需要传,python解释器会自己把实例变量传进去。
在类中定义多个函数相互调用:
class Person(object):
def init(self,x,y):
self.x = x
self.y = y
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">sum</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">y</span>
<span class="k">return</span> <span class="nb">sum</span>
<span class="k">def</span> <span class="nf">square</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">squr</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">x</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span><span class="o">+</span><span class="nb">pow</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">y</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span>
<span class="k">return</span> <span class="n">squr</span>
<span class="k">def</span> <span class="nf">add_square</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">()</span><span class="o">+</span><span class="bp">self</span><span class="o">.</span><span class="n">square</span><span class="p">()</span>
<span class="k">return</span> <span class="n">c</span>
student = Person(3,4)
print(student.add())
print(student.square())
print(’--------- 我是可爱的分割线-----------’)
print(student.add_square())
输出结果:
7
25
--------- 我是可爱的分割线-----------
32
通过上述的例子可以看出,与普通的函数相比,在类中定义的函数只有两点点不同:
- 第一个参数永远是 self ,并且调用时不用传递该参数。
- 类中函数相互调用要加 self,如上述代码中的c = self.add()+self.square()。
除此之外,类的方法和普通函数没甚区别,当然也可以使用 默认参数、可变参数和关键字参数,例子如下:
class Person(object):
def init(self,x,y):
self.x = x
self.y = y
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">z</span><span class="o">=</span><span class="mi">16</span><span class="p">):</span> <span class="c1"># 设置 默认变量 z =16,这只是个普通的局部变量,非实例变量,实例变量需要 self.z = z,这样定义</span>
<span class="nb">sum</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">z</span>
<span class="k">return</span> <span class="nb">sum</span>
<span class="k">def</span> <span class="nf">square</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">squr</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">x</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span><span class="o">+</span><span class="nb">pow</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">y</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span>
<span class="k">return</span> <span class="n">squr</span>
<span class="k">def</span> <span class="nf">add_square</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">z</span><span class="p">):</span> <span class="c1"># 调用时传入变量,这也是个普通的局部变量,非实例变量 </span>
<span class="n">c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">()</span><span class="o">+</span><span class="bp">self</span><span class="o">.</span><span class="n">square</span><span class="p">()</span> <span class="o">+</span> <span class="n">z</span>
<span class="k">return</span> <span class="n">c</span>
student = Person(3,4)
print(student.add())
print(student.square())
print(’--------- 我是可爱的分割线-----------’)
print(student.add_square(16))
输出结果:
23
25
--------- 我是可爱的分割线-----------
64
看了上述的例子可能还是不明白 self 到底是个什么鬼,为啥要使用self这鬼东西 ?,没关系,往下看。
其实 self 这家伙简单的说就是把 class 中 定义的 变量和函数 变成 实例变量和实例函数,作为类 class 的成员,使得成员间能互相调用,而不需要从外部调用 数据(即变量)和 方法(即 函数),以实现数据的封装,以上面的 Person 类为例:创建实例的时候需要给出实例变量 x,y, 调用函数时给出 z ,调用很容易,却不知道内部实现的细节。
总之,类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都相互独立、互不影响;方法是与实例绑定的函数,和普通的函数不同,方法可以直接访问实例的数据。
其实 self 中存储的是 实例变量 和 实例函数 的属性,可以理解为一个字典( dict ),如:{‘name’:‘zhang’,‘age’:‘18’}就是这些。
注意只有数据属性,并没有创建新的类的方法。 类----->通过实例化生成----对象---->(对象只是一串类似于字典的数据,没有把类的里的方法复制给你,python没有new这个方法!)
class Person(object):
def init(self,x,y):
self.x = x
self.y = y
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">z</span><span class="o">=</span><span class="mi">16</span><span class="p">):</span> <span class="c1"># 设置 z 为实例变量,即 self.z = z, z 是 class 的一个成员了,而非普通局部变量</span>
<span class="bp">self</span><span class="o">.</span><span class="n">z</span> <span class="o">=</span> <span class="n">z</span>
<span class="nb">sum</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">z</span> <span class="c1"># z虽然已被实例化,但是依然可以当作 普通变量来用</span>
<span class="k">return</span> <span class="nb">sum</span>
<span class="k">def</span> <span class="nf">square</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">squr</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">x</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span><span class="o">+</span><span class="nb">pow</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">y</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span>
<span class="k">return</span> <span class="n">squr</span>
<span class="k">def</span> <span class="nf">add_square</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">c</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">()</span><span class="o">+</span><span class="bp">self</span><span class="o">.</span><span class="n">square</span><span class="p">()</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">z</span> <span class="c1"># 调用实例变量 z </span>
<span class="k">return</span> <span class="n">c</span>
student = Person(3,4)
print(student.add())
print(student.square())
print(’--------- 我是可爱的分割线-----------’)
print(student.add_square())
print(student.z) # 函数add 中的 z 被实例化以后,就可以利用实例化的方法访问它
输出结果:
23
25
--------- 我是可爱的分割线-----------
64
16
通过这个例子可以看出, z 本来是 add() 函数的默认形参,通过将其实例化,就可以在其他函数体内调用 实例变量 z 。被实例化以后,就可以利用实例化的方法访问它。
2.3 那么 self 到底是什么?
class Box(object):
def init(self, boxname, size, color):
self.boxname = boxname
self.size = size
self.color = color # self就是用于存储对象属性的集合,就算没有属性self也是必备的
<span class="k">def</span> <span class="nf">open</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">myself</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'-->用自己的myself,打开那个</span><span class="si">%s</span><span class="s1">,</span><span class="si">%s</span><span class="s1">的</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">myself</span><span class="o">.</span><span class="n">color</span><span class="p">,</span> <span class="n">myself</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="n">myself</span><span class="o">.</span><span class="n">boxname</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'-->用类自己的self,打开那个</span><span class="si">%s</span><span class="s1">,</span><span class="si">%s</span><span class="s1">的</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">color</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">boxname</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'-->关闭</span><span class="si">%s</span><span class="s1">,谢谢'</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">boxname</span><span class="p">)</span>
b = Box(‘魔盒’, ‘14m’, ‘红色’)
b.close()
b.open(b) # 本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。
print(b.dict) # 这里返回的就是self本身,self存储属性,没有动作。
输出结果:
–>关闭魔盒,谢谢
–>用自己的myself,打开那个红色,14m的魔盒
–>用类自己的self,打开那个红色,14m的魔盒
{‘boxname’: ‘魔盒’, ‘size’: ‘14m’, ‘color’: ‘红色’}
self代表类的实例,而非类;self 就是 对象/实例 属性集合。
Box 是个类-----》self 实例化------》 b对象/ 实例。
class 抽象体------》实例化------》对象/实例,含有属性:{‘boxname’:‘魔盒’, ‘size’:‘14m’, ‘color’:‘red’},即 self。
self 看似是整个对象,实际上清楚地描述了类就是产生对象的过程,描述了 self 就是得到了 对象,所以 self 内的键值可以直接使用。
正如自然界中一个有效的对象,必须包括:1、描述对象的属性;2、对象的方法。所以 self是必须的,也是对象中重要的特性。
看下面的代码,感觉就更神奇了:
class Box(object):
def myInit(mySelf, boxname, size, color):
mySelf.boxname = boxname
mySelf.size = size
mySelf.color = color # 自己写一个初始化函数,一样奏效,甚至不用self命名。其它函数当中用标准self
return mySelf # 返回给实例化过程一个对象!神奇!并且含有对象属性/字典
<span class="c1"># def __init__(self, boxname, size, color):</span>
<span class="c1"># self.boxname = boxname</span>
<span class="c1"># self.size = size</span>
<span class="c1"># self.color = color #注释掉原来标准的初始化</span>
<span class="k">def</span> <span class="nf">open</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">myself</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'-->用自己的myself,打开那个</span><span class="si">%s</span><span class="s1">,</span><span class="si">%s</span><span class="s1">的</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">myself</span><span class="o">.</span><span class="n">color</span><span class="p">,</span> <span class="n">myself</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="n">myself</span><span class="o">.</span><span class="n">boxname</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'-->用类自己的self,打开那个</span><span class="si">%s</span><span class="s1">,</span><span class="si">%s</span><span class="s1">的</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">myself</span><span class="o">.</span><span class="n">color</span><span class="p">,</span> <span class="n">myself</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="n">myself</span><span class="o">.</span><span class="n">boxname</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'-->关闭</span><span class="si">%s</span><span class="s1">,谢谢'</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">boxname</span><span class="p">)</span>
# 经过改造,运行结果和标准初始化没区别
b = Box().myInit(‘魔盒’, ‘14m’, ‘红色’)
# b = Box(‘魔盒’, ‘14m’, ‘红色’)#注释掉原来标准的初始化方法
b.close()
b.open(b) # 本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。
print(b.dict) # 这里返回的就是self本身,self存储属性,没有动作。
输出结果:
–>关闭魔盒,谢谢
<main.Box object at 0x0000027FF57C6B70>
–>用自己的myself,打开那个红色,14m的魔盒
–>用类自己的self,打开那个红色,14m的魔盒
{‘boxname’: ‘魔盒’, ‘size’: ‘14m’, ‘color’: ‘红色’}
换个角度来讲,对类的操作有:1、定义属性 ; 2、调用方法
对类的反馈有:1、得到属性 ; 2、执行方法
在 class 类的函数中,为什么 self是必要的,因为 self 是对象的载体,可以理解成一个字典,看下面代码:
class Box(object):
def myInit(mySelf, boxname, size, color):
print(mySelf.dict)#显示为{}空字典
mySelf.boxname = boxname
mySelf.dict[‘aa’] = ‘w’#甚至可以像字典一样操作
mySelf.size = size
mySelf.color = color # 自己写一个初始化函数,一样奏效,甚至不用self命名。其它函数当中用标准self
return mySelf # 返回给实例化过程一个对象!神奇!并且含有对象属性/字典
<span class="c1"># def __init__(self, boxname, size, color):</span>
<span class="c1"># self.boxname = boxname</span>
<span class="c1"># self.size = size</span>
<span class="c1"># self.color = color #注释掉原来标准的初始化</span>
<span class="k">def</span> <span class="nf">open</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">myself</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'-->用自己的myself,打开那个</span><span class="si">%s</span><span class="s1">,</span><span class="si">%s</span><span class="s1">的</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">myself</span><span class="o">.</span><span class="n">color</span><span class="p">,</span> <span class="n">myself</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="n">myself</span><span class="o">.</span><span class="n">boxname</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'-->用类自己的self,打开那个</span><span class="si">%s</span><span class="s1">,</span><span class="si">%s</span><span class="s1">的</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">myself</span><span class="o">.</span><span class="n">color</span><span class="p">,</span> <span class="n">myself</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="n">myself</span><span class="o">.</span><span class="n">boxname</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'-->关闭</span><span class="si">%s</span><span class="s1">,谢谢'</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">boxname</span><span class="p">)</span>
# 经过改造,运行结果和标准初始化没区别
b = Box().myInit(‘魔盒’, ‘14m’, ‘红色’)
# b = Box(‘魔盒’, ‘14m’, ‘红色’)#注释掉原来标准的初始化方法
b.close()
b.open(b) # 本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。
print(b.dict) # 这里返回的就是self本身,self存储属性,没有动作。
输出结果:
{}
–>关闭魔盒,谢谢
<main.Box object at 0x0000021F2C016C18>
–>用自己的myself,打开那个红色,14m的魔盒
–>用类自己的self,打开那个红色,14m的魔盒
{‘boxname’: ‘魔盒’, ‘aa’: ‘w’, ‘size’: ‘14m’, ‘color’: ‘红色’}
注意此处的: mySelf.dict[‘aa’] = ‘w’ #甚至可以像字典一样操作; 在 b.dict 的结果中显示为:‘aa’:'w’
故可以把 self 理解成存储 实例化对象属性的字典(dict), self 存储属性,而没有动作执行,self总是指调用时的类的实例。
python 中一些特殊的实例变量:
- 私有变量(private),只有内部可以访问,外部不能访问,私有变量是在名称前以两个下划线开头,如:__name,其实私有变量也不是完全不能被外部访问。
- 在Python中,变量名类似
xxx
的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用name
、score
这样的变量名。 - 以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。[1]
参考
- ^读懂python中的self https://blog.csdn.net/xrinosvip/article/details/89647884
- ^python里面的self,是谁啊? https://zhuanlan.zhihu.com/p/95788606