在定义类的过程中,无论是显示创建类的构造方法,还是向类中添加实例方法,都要求将 self 参数作为方法的第一个参数,那么我们如何去理解这个self呢?下面就带你简单了解一下
通过比喻的方式去理解
self并不是一个固定的参数,而是约定俗成。怎么理解呢?比如说:大家一听到大熊猫就知道这个是国宝(在这里特指国家保护动物吧),但是国宝并不等于大熊猫,用这两个比喻就是:
国宝=类的第一个传参,属于描述,也就是泛类(国宝里面包含大熊猫)
大熊猫=属于类的第一个传参,并且指定了一个种类(熊猫属于国宝)
还不理解的话可以继续看这个比喻:
在编程中,变量与变量值是最基础的一个知识点,那么把这个self比喻变量是怎样的呢?
变量名=变量值
类的第一个传参=self
也就是说类的第一个传参是一个变量,而self是一个变量值,所以self也可以是seif、seff,这并不影响程序的运行,你喜欢就好
但是这个self并不只是变量名与变量值之间的关系那么简单,下面看案例:
举个栗子
在这里我创建一个国宝(National treasure)的类,然后分别定义大熊猫(panda)和东北虎(Northeast Tiger),然后分别使用约定俗成的self与ka作为第一个参数
class National_treasure: def __init__(self,name): print("正在执行构造方法,当前实例ID---> [ %s ],当前实例类--> [ %s ]" % (self, name)) def panda(self,address): print("我是国宝下面的大熊猫,我住在--->[ %s ]当前实例ID--->[ %s ]" %(address, self)) def Northeast_Tiger(ka, address): print("我是国宝下面的东北虎,我住在--->[ %s ]当前实例ID--->[ %s ]" %(address, ka))get = National_treasure(name='省份')get.panda(address='四川')get.Northeast_Tiger(address='东北')g = National_treasure(name='区域')g.panda(address='中国')g.panda('中国东北')
运行结果
从结果中我们可以看出一些东西,首先看第一个实例:
get = National_treasure(name='省份')get.panda(address='四川')get.Northeast_Tiger(address='东北')
正在执行构造方法,当前实例ID---> [ <__main__.national_treasure object at> ],当前实例类--> [ 省份 ]我是国宝下面的大熊猫,我住在--->[ 四川 ]当前实例ID--->[ <__main__.national_treasure object at> ]我是国宝下面的东北虎,我住在--->[ 东北 ]当前实例ID--->[ <__main__.national_treasure object at> ]
从结果中可以看出,无论我是使用self还是ka作为第一个传参,它得到的对象ID都是同一个,这是第一次实例化能看出的东西,然后看第二次:
g = National_treasure(name='区域')g.panda(address='中国')g.Northeast_Tiger('中国东北')
执行结果:
正在执行构造方法,当前实例ID---> [ <__main__.national_treasure object at> ],当前实例类--> [ 区域 ]我是国宝下面的大熊猫,我住在--->[ 中国 ]当前实例ID--->[ <__main__.national_treasure object at> ]我是国宝下面的东北虎,我住在--->[ 中国东北 ]当前实例ID--->[ <__main__.national_treasure object at> ]
从两次结果上来看,不同的实例传入不同的参数会得到不一样(部分)的结果,例如:
在圈圈中,除了ID是随机的,其他传参值都可以通过人为的改变,在这点上可以看出,其实类跟我们的函数没有任何区别,类中的第一个参数仅仅是为了告诉这个程序哪个地方调用了它,然后它可以准确的返回数据,当然,类并不是简单的理解为一个函数,这只是针对传参方面而言。
总结:
self只是一个有点抽象的东西,实际上认真琢磨一下就懂了,你喜欢的话可以把self改成自己的名字,当然,不建议在团队开发中采用这个方法
虽然self可以随意命名,但是必不可少,你可以随意,但不能没有