Python中self关键字深度解析:原理、用法与注意事项

巷口听风
巷口听风
发布时间:2026-10-13 | 1人浏览过
原创

本文深入解析Python类中self关键字的核心作用。阐述self作为实例对象引用,如何用于访问属性和调用方法,对比Java中的this。详细讲解__init__初始化中self的使用,类内函数相互调用规则,以及私有变量、特殊变量和单下划线变量的访问权限与命名规范,帮助开发者彻底理解Python面向对象机制。

Python中self的基本概念与作用

在Python的类定义中,函数(方法)的第一个参数被规定为实例对象本身。按照惯例,该参数命名为self。其功能类似于Java中的this,用于指代当前类的实例,从而允许访问该实例的属性和调用其方法。

class是面向对象设计的核心概念,而instance(即object,对象)则是根据class模板创建的具体实体。

一个类(class)应当包含数据以及操作这些数据的方法,通俗来说,即包含属性和函数(方法调用)。

在类的代码(函数)中,为什么要使用self?

在类的函数代码中,需要访问当前实例中的变量和函数,即访问Instance中的:

对应的变量(property):Instance.PropertyName,用于读取之前的值或写入新的值。

调用对应函数(function):Instance.function(),即执行相应的动作。

  • 要访问实例的变量并调用实例的函数,必然需要对应的实例Instance对象本身。
  • 因此,Python规定函数的第一个参数必须是实例对象本身,并建议约定俗成地将其命名为self。
  • 所以,我们需要使用self(因为必须用到它)。

类的定义与实例化过程

首先,在Python中类的定义方式如下:

在Python中,类是通过关键字class定义的:

class后紧跟类名,例如Person。类名通常以大写字母开头,紧接着是(object),表示该类继承自哪个父类。通常如果没有合适的继承类,就使用object类,这是所有类最终都会继承的基类。

class Person(object):  
    pass

将Person类实例化,创建实例是通过类名加()实现的。

class Person(object):  
    pass
student = Person()  # 创建类的实例化
print(student)
print(Person)

可以看到,变量student指向的是一个Person对象,后面的0x0000026EE434D8D0是内存地址,每个对象的地址都不同,而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)

__init__初始化方法中self的使用

上述方法虽然可以为类的实例变量绑定属性,但不够便捷和优雅。由于类起到模板作用,创建实例时可将必须绑定的属性强制填入。在Python中,通过类中常用的__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)

传入空参数的情况会报错:

class Person(object):  
    def __init__(self,name,score):    
        self.name = name    
        self.score = score    
student = Person()   # 此处应该有参数传入,却没有传
print(student.name)
print(student.score)

注意:

1、__init__方法的第一个参数永远是self,表示创建的实例本身。因此,在__init__方法内部,可以将各种属性绑定到self,因为self指向创建的实例本身。

2、使用了__init__方法后,创建实例时不能传入空参数,必须传入与__init__方法匹配的参数,但self不需要手动传入,Python解释器会自动将实例变量传进去。

类内函数相互调用与参数处理

在类中定义多个函数相互调用。

class Person(object):  
    def __init__(self,x,y):    
        self.x = x    
        self.y = y      
    def add(self):    
        sum = self.x + self.y    
        return sum    
    def square(self):    
        squr = pow(self.x,2)+pow(self.y,2)    
        return squr  
    def add_square(self):    
        c = self.add()+self.square()    
        return c    
student = Person(3,4)
print(student.add())
print(student.square())
print('--------- 我是可爱的分割线-----------')
print(student.add_square())

通过上述例子可以看出,与普通函数相比,类中定义的函数只有两点不同:

1、第一个参数永远是self,且调用时不需要传递该参数。

2、在类中函数相互调用时要加self,如上例中:c = self.add()+self.square(),不加self会报错:函数未定义,见下图:

除此之外,类的方法与普通函数没有太大区别,当然也可以使用默认参数、可变参数和关键字参数,例子如下:

class Person(object):  
    def __init__(self,x,y):    
        self.x = x    
        self.y = y          
    def add(self,z=16):     # 设置 默认变量 z =16,这只是个普通的局部变量,非实例变量,实例变量需要 self.z = z,这样定义    
        sum = self.x + self.y + z    
        return sum    
    def square(self):    
        squr = pow(self.x,2)+pow(self.y,2)    
        return squr  
    def add_square(self,z):    # 调用时传入变量,这也是个普通的局部变量,非实例变量     
        c = self.add()+self.square() + z    
        return c    
student = Person(3,4)
print(student.add())
print(student.square())
print('--------- 我是可爱的分割线-----------')
print(student.add_square(16))

深入理解self的本质与对象封装

看了上述例子可能仍不明白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          
    def add(self,z=16):   # 设置 z 为实例变量,即 self.z = z, z 是 class 的一个成员了,而非普通局部变量    
        self.z = z    
        sum = self.x + self.y + z # z虽然已被实例化,但是依然可以当作 普通变量来用
        return sum    
    def square(self):    
        squr = pow(self.x,2)+pow(self.y,2)    
        return squr  
    def add_square(self):        
        c = self.add()+self.square() + self.z # 调用实例变量 z     
        return c    
student = Person(3,4)
print(student.add())
print(student.square())
print('--------- 我是可爱的分割线-----------')
print(student.add_square())
print(student.z)     # 函数add 中的 z 被实例化以后,就可以利用实例化的方法访问它

通过这个例子可以看出,z本来是add()函数的默认形参,通过将其实例化,就可以在其他函数体内调用实例变量z。

被实例化以后,就可以利用实例化的方法访问它。

self作为对象载体与属性集合

那么self到底是什么?

class Box(object):
  def __init__(self, boxname, size, color):
    self.boxname = boxname
    self.size = size
    self.color = color # self就是用于存储对象属性的集合,就算没有属性self也是必备的
  def open(self, myself):
    print('-->用自己的myself,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))
    print('-->用类自己的self,打开那个%s,%s的%s' % (self.color, self.size, self.boxname))
  def close(self):
    print('-->关闭%s,谢谢' % self.boxname)
b = Box('魔盒', '14m', '红色')
b.close()
b.open(b) # 本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。
print(b.__dict__) # 这里返回的就是self本身,self存储属性,没有动作。

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 # 返回给实例化过程一个对象!神奇!并且含有对象属性/字典
  # def __init__(self, boxname, size, color):
  #   self.boxname = boxname
  #   self.size = size
  #   self.color = color #注释掉原来标准的初始化
  def open(self, myself):
    print(self)
    print('-->用自己的myself,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))
    print('-->用类自己的self,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))
  def close(self):
    print('-->关闭%s,谢谢' % self.boxname)
# 经过改造,运行结果和标准初始化没区别
b = Box().myInit('魔盒', '14m', '红色')
# b = Box('魔盒', '14m', '红色')#注释掉原来标准的初始化方法
b.close()
b.open(b) # 本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。
print(b.__dict__) # 这里返回的就是self本身,self存储属性,没有动作。

对类的操作与反馈机制

换个角度来讲,对类的操作有:

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 # 返回给实例化过程一个对象!神奇!并且含有对象属性/字典
  # def __init__(self, boxname, size, color):
  #   self.boxname = boxname
  #   self.size = size
  #   self.color = color #注释掉原来标准的初始化
  def open(self, myself):
    print(self)
    print('-->用自己的myself,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))
    print('-->用类自己的self,打开那个%s,%s的%s' % (myself.color, myself.size, myself.boxname))
  def close(self):
    print('-->关闭%s,谢谢' % self.boxname)
# 经过改造,运行结果和标准初始化没区别
b = Box().myInit('魔盒', '14m', '红色')
# b = Box('魔盒', '14m', '红色')#注释掉原来标准的初始化方法
b.close()
b.open(b) # 本来就会自动传一个self,现在传入b,就会让open多得到一个实例对象本身,print看看是什么。
print(b.__dict__) # 这里返回的就是self本身,self存储属性,没有动作。

注意此处的:mySelf.__dict__['aa'] = 'w' #甚至可以像字典一样操作;在b.__dict__的结果中显示为:'aa':'w'。

故可以把self理解成存储实例化对象属性的字典(dict),self存储属性,而没有动作执行。

self总是指调用时的类的实例。

Python特殊实例变量命名规范

Python中一些特殊的实例变量:

1、私有变量(private),只有内部可以访问,外部不能访问。私有变量是在名称前以两个下划线开头,如:__name。其实私有变量也不是完全不能被外部访问,不能直接访问是因为Python解释器对外把__name变量改成了_类名__name,所以仍可以通过_类名__name来访问__name。

2、在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量。特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。

3、以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的。但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

以上就是一文读懂Python中的self的详细内容,更多请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表