Python中self详细解析

本文围绕Python编程展开,介绍了Class、instance、object的概念,将Class比作组装工厂,instance是工厂生产的产品。还区分了method和function,指出method依赖于class和instance。此外,详细解析了self的作用,它用于访问实例变量和函数,实现数据封装,同时介绍了Python中特殊实例变量的规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是Class,instance,object

Class:可以理解为一个组装工厂。假设需要生产一个机器人,需要先搭建工厂。先确定:我们要先安装胳膊,再安装头,流水线就打好了。其中头和胳膊的数量可以调。

class BuildRobot():
    def __init__(self,armcount,headcount):
        self.armcount = armcount
        self.headcount = headcount

所以这里的class,就是搭了一个工厂叫BuildRobot。‘init’ 就是告诉这个流水线,首先你需要这个机器人有几个胳膊(‘armcount’),有几个脑袋(‘headcount’)。
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

什么是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来:

```python
colorful_robot = BuildRobot(2,1)
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

这个外包的上色工厂,不管你这个东西是从哪个工厂来的,无论你是个机器人还是机器狗,反正我就拿来,给胳膊上色。

注意method其实有两种,一种是instance method,一种是class method。

  • instance method就相当于对于机器人这个产品进行各种修改的车间。我给机器人上色,不影响我这个工厂的外形对吧?
  • class method,是对这个工厂,这个class的属性进行修改的车间,比如我有一个车间负责把工厂涂成红色的。这个行为并不影响我造出来的机器人的大小颜色属性。

self详细解析

在Python类中规定,函数的第一个参数是实例对象本身,并且约定俗成,把其名字写为self。其作用相当于java中的this,表示当前类的对象,可以调用当前类中的属性和方法。

class是面向对象的设计思想,instance(也即是 object,对象)是根据 class 创建的。

一个类(class)应该包含数据和操作数据的方法,通俗来讲就是 属性 和 函数(即调用方法)

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

  1. 对应的变量(property):Instance.ProperyNam,去读取之前的值和写入新的值。
  2. 调用对应函数(function):Instance.function(),即执行对应的动作。

而需要访问实例的变量和调用实例的函数,当然需要对应的实例Instance对象本身。而Python中就规定好了,函数的第一个参数,就必须是实例对象本身,并且建议,约定俗成,把其名字写为self。所以,我们需要self(需要用到self)。

**在python中类的定义:**class 后面紧跟 类名,即 Person,类名通常大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的,通常,如果没有合适的 继承类,就使用 object 类,这是所有类最终都会 继承的类。

class Personobject:
    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

注意

  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())

输出结果

7
25
--------- 我是可爱的分割线-----------
32

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

第一个参数永远是 self ,并且调用时不用传递该参数。
类中函数相互调用要加 self,如上述代码中的c = self.add()+self.square()

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

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))

输出结果:

23
25
--------- 我是可爱的分割线-----------
64

其实 self 、简单的说就是把 class 中定义的变量和函数变成实例变量和实例函数,作为类 class 的成员,使得成员间能互相调用,而不需要从外部调用数据(即变量)和方法(即 函数),以实现数据的封装,以上面的 Person 类为例:创建实例的时候需要给出实例变量 x,y, 调用函数时给出 z ,调用很容易,却不知道内部实现的细节。

其实 self 中存储的是 实例变量 和 实例函数 的属性,可以理解为一个字典( dict ),如:{‘name’:‘zhang’,‘age’:‘18’}就是这些。

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

私有变量(private),只有内部可以访问,外部不能访问,私有变量是在名称前以两个下划线开头,如:__name,其实私有变量也不是完全不能被外部访问。

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

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值