当前位置:首页>python>《Python 从入门到精通》073|实例属性与实例方法:对象为什么“各有各的数据”

《Python 从入门到精通》073|实例属性与实例方法:对象为什么“各有各的数据”

  • 2026-10-11 05:47:41
《Python 从入门到精通》073|实例属性与实例方法:对象为什么“各有各的数据”
分享最近看到的一段话,致敬人到中年的90后:

14岁鲜衣怒马,心比天高,满眼皆是来日可期的万丈风光 24岁历经起落,方知人各有命,世事自有无常法。后来才懂,那股一往无前的少年心气,是此生仅有、不可再生的滚烫宝藏,一旦褪去,便再也寻不回当初一腔孤勇的模样。

上一章我们已经学会了怎么定义一个类,也知道了什么叫对象。

比如你已经能写出这样的代码:

classCat:defmeow(self):        print('喵喵喵')

也知道可以这样创建对象:

cat1 = Cat()cat1.meow()

但学到这里,很多人很快就会冒出一个新问题:

类我会写了。对象我也会创建了。 可为什么现在创建出来的对象,看起来都差不多?cat1 和 cat2 有什么区别? 它们怎么才能一个叫“咪咪”,一个叫“雪球”,一个 2 岁,一个 3 岁?

这就要进入这一章的核心了:

实例属性 实例方法

这一章非常关键。因为从这里开始,对象才真正“活起来”。不再只是一个空壳子,而是开始拥有各自不同的数据。

一、先看问题出在哪

先看下面这段代码:

classDog:defbark(self):        print('汪汪汪')dog1 = Dog()dog2 = Dog()dog1.bark()dog2.bark()

这段代码当然没问题。 但你会发现,dog1 和 dog2 现在几乎没区别。它们都能叫,但你并不知道谁是谁。

现实里,一只狗通常不会只有“会叫”这一件事。它还会有很多自己的信息,比如:

名字 年龄 颜色 品种

而且这些信息,不同对象之间通常是不一样的。

比如:

dog1 叫大黄,2 岁,黄色dog2 叫豆豆,1 岁,白色

那这些“对象自己的数据”,该放在哪里?

答案就是:实例属性。

二、什么叫实例属性

你可以把实例属性理解成:

某个具体对象自己拥有的数据。

注意,是“某个具体对象自己拥有”。

比如学生对象的姓名、年龄、成绩。 比如汽车对象的品牌、颜色、速度。 比如手机对象的型号、电量、价格。

这些东西都不是整个类统一只有一份,而是每个对象可以各有各的值。

所以它叫实例属性。 因为它属于实例,也就是属于某个具体对象。

你可以先记住一句最朴素的话:

实例属性,就是对象身上的信息。

三、最直接的写法:先创建对象,再给它加属性

在 Python 里,最直观的入门写法是这样的:

classStudent:passstu1 = Student()stu1.name = '张三'stu1.age = 18stu1.score = 95print(stu1.name)print(stu1.age)print(stu1.score)

输出结果:

张三1895

这里发生了什么?

我们先创建了一个 Student 对象。 然后给这个对象动态加上了三个属性:

nameagescore

而这些属性的值,都是属于 stu1 这个对象自己的。

这就已经是实例属性了。

四、不同对象,属性值可以不同

再看一个更完整的例子:

classStudent:passstu1 = Student()stu1.name = '张三'stu1.age = 18stu1.score = 95stu2 = Student()stu2.name = '李四'stu2.age = 19stu2.score = 88print(stu1.name, stu1.age, stu1.score)print(stu2.name, stu2.age, stu2.score)

输出结果:

张三 1895李四 1988

注意这里最重要的一点:

虽然 stu1 和 stu2 都来自同一个 Student 类, 但它们各自保存的数据是不同的。

这就是对象为什么“各有各的数据”。

也就是说:

类是同一个模板 对象是不同个体 实例属性让每个个体都能带着自己不同的信息

这一步想通以后,面向对象的感觉就会一下清晰很多。

五、属性访问为什么要写成 对象.属性

你应该已经发现了,实例属性最常见的访问方式就是:

对象.属性

例如:

stu1.namestu1.agestu1.score

这种写法非常符合现实表达。

不是“有一个孤零零的名字变量”。 而是“张三这个学生对象的名字”。

不是“有一个孤零零的成绩变量”。 而是“这个对象自己的成绩”。

所以你会发现,类和对象让数据的归属关系变得特别清楚。

前面如果你写:

name = '张三'age = 18score = 95

这些变量是散的。 可一旦写成:

stu1.name = '张三'stu1.age = 18stu1.score = 95

信息立刻就被组织起来了。

六、实例方法又是什么

如果说实例属性是对象“有什么”,那实例方法就是对象“能做什么”。

其实上一章你已经见过实例方法了。

比如:

classDog:defbark(self):        print('汪汪汪')

这里的 bark(),本质上就是一个实例方法。

为什么叫实例方法?

因为它通常是由某个具体对象来调用的,比如:

dog1.bark()

这不是一个悬空动作,而是“dog1 这个对象执行了 bark 这个行为”。

所以你可以这样记:

实例属性,是对象的数据。 实例方法,是对象的行为。

这两个东西放在一起,才组成了一个完整的对象。

七、实例方法和普通函数,到底差在哪

先看普通函数:

defsay_hello():    print('你好')

调用时这样写:

say_hello()

再看类里的方法:

classStudent:defsay_hello(self):        print('你好,我是学生')

调用时这样写:

stu1 = Student()stu1.say_hello()

表面上看,好像都只是打印一句话。 但本质区别在于:

普通函数没有明显归属。 实例方法属于某个对象。

这就意味着,实例方法通常会和这个对象自己的数据配合使用。

比如你很快就会看到,方法里不只是打印固定文字,而是能用到对象自己的姓名、年龄这些属性。

这才是它真正厉害的地方。

八、为什么方法里会有 self

这一章先不把 self 讲得太深,第75章会专门彻底讲透。 但现在你一定要先建立一个非常实用的直觉:

self 通常可以先理解成“当前这个对象自己”。

看代码:

classStudent:defintroduce(self):        print('大家好')

这里的 introduce(self) 不是随便多写了一个参数,而是在为“对象自己”预留位置。

因为以后方法很可能要访问这个对象自己的属性,比如姓名、年龄。 没有 self,方法就不知道它现在到底是在处理哪个对象。

你现在先别死抠底层。 先把它粗略理解成:

谁来调用这个方法,self 就代表谁。

这个感觉先有了,后面讲细节时就不会慌。

九、让方法真正用上对象自己的属性

下面这个例子,是这一章最关键的转折点。

classStudent:defintroduce(self):        print(f'大家好,我叫{self.name},今年{self.age}岁,成绩是{self.score}分')stu1 = Student()stu1.name = '张三'stu1.age = 18stu1.score = 95stu2 = Student()stu2.name = '李四'stu2.age = 19stu2.score = 88stu1.introduce()stu2.introduce()

输出结果:

大家好,我叫张三,今年18岁,成绩是95分大家好,我叫李四,今年19岁,成绩是88分

这一段非常重要,你一定要看懂。

同一个 introduce() 方法,为什么对 stu1 和 stu2 输出不同?

因为方法里用到的是:

self.nameself.ageself.score

而 self 会指向当前调用这个方法的对象。

也就是说:

stu1.introduce() 里,self 指的是 stu1stu2.introduce() 里,self 指的是 stu2

所以同一个方法,能根据不同对象身上的属性,表现出不同结果。

这就是实例方法真正有意思的地方。

十、现在你要真正理解“对象各有各的数据”了

很多新手学到这里,才会第一次真正感觉到类的价值。

类里方法是同一份。 但对象里的属性值可以不同。 所以同样的方法,落在不同对象上,就会产生不同结果。

这特别像现实世界。

“自我介绍”这个行为,所有学生都会。 但每个学生介绍出来的内容不一样。 因为每个人自己的姓名、年龄、成绩不同。

这就是面向对象最自然的表达方式。

不是重复写很多相似代码, 而是写一个通用的方法,让不同对象带着自己的数据去执行。

十一、实例属性本质上是属于对象,不属于类

这一点特别重要。

比如:

classStudent:passstu1 = Student()stu1.name = '张三'stu2 = Student()stu2.name = '李四'

这里的 name 不是整个 Student 类统一只有一个值。 而是 stu1 有自己的 name,stu2 也有自己的 name。

所以你一定不要把实例属性想成“类里写了一个全局变量”。

更准确的理解是:

同一个类创建出来的每个对象,都可以拥有自己独立的一份属性数据。

这也是为什么对象彼此之间不会互相覆盖。

你改 stu1.name,不会自动改掉 stu2.name。 因为它们本来就不是同一份数据。

十二、用一个更贴近现实的例子再理解一次

比如定义一个 Car 类:

classCar:defshow_info(self):        print(f'这辆车的品牌是{self.brand},颜色是{self.color},价格是{self.price}元')

创建两个对象:

car1 = Car()car1.brand = '比亚迪'car1.color = '白色'car1.price = 120000car2 = Car()car2.brand = '特斯拉'car2.color = '黑色'car2.price = 260000car1.show_info()car2.show_info()

输出结果:

这辆车的品牌是比亚迪,颜色是白色,价格是120000元这辆车的品牌是特斯拉,颜色是黑色,价格是260000元

你看,同一个 Car 类,同一个 show_info() 方法, 因为两个对象的属性不同,所以展示出来的信息也不同。

这已经非常接近真实开发里的写法了。

十三、实例方法里不只是读取属性,也可以修改属性

对象的方法不一定只是“展示信息”,也可以修改对象自己的状态。

例如:

classDog:defgrow_up(self):        self.age = self.age + 1        print(f'{self.name} 长大了一岁,现在 {self.age} 岁了')dog1 = Dog()dog1.name = '大黄'dog1.age = 2dog1.grow_up()dog1.grow_up()

输出结果:

大黄 长大了一岁,现在 3 岁了大黄 长大了一岁,现在 4 岁了

这说明什么?

说明实例方法不仅能读取 self.age,还能改写 self.age。

也就是说,方法和属性不是分开的两套东西。 方法往往就是围绕对象自己的属性来工作的。

这才是真正完整的对象:

有自己的数据 也有处理自己数据的能力

十四、实例属性不提前赋值会怎样

这里要提前提醒你一个很容易踩的坑。

看下面这段代码:

classStudent:defintroduce(self):        print(self.name)stu1 = Student()stu1.introduce()

这段代码会报错。 因为你根本还没有给 stu1 设置 name 属性。

也就是说,虽然 Python 允许你后面动态加属性,但如果你方法里要用某个属性,就得保证它已经存在。

这也是为什么下一章会讲 __init__。 因为用现在这种“先创建对象,再手动一个个补属性”的方式,虽然能帮助你理解实例属性,但写起来并不够稳,也不够规范。

所以这一章的重点,是先让你理解原理。 下一章我们就会把这种写法升级成更标准的方式。

十五、先别嫌这种写法麻烦,它正适合入门

有些人看到这里会觉得:

每次都这样写:

stu1 = Student()stu1.name = '张三'stu1.age = 18stu1.score = 95

是不是有点麻烦。

是的,确实麻烦。 但它有一个非常大的优点:直观。

因为它把“对象”和“属性”之间的关系,几乎是掰开给你看了。

你能清楚看到:

先有对象 再给对象加数据 方法再去使用这些数据

这个理解过程非常值钱。 因为如果一开始就把 __init__、参数传递全塞进来,很多新手会直接把类学成死记语法。

而现在这种写法,虽然笨一点,却特别适合理解本质。

十六、再看一个学生对象的完整例子

下面给你一个适合反复敲一遍的小案例:

classStudent:defintroduce(self):        print(f'我叫{self.name},今年{self.age}岁,考试得了{self.score}分')defis_passed(self):if self.score >= 60:            print(f'{self.name} 已经及格了')else:            print(f'{self.name} 没有及格')stu1 = Student()stu1.name = '张三'stu1.age = 18stu1.score = 95stu2 = Student()stu2.name = '李四'stu2.age = 19stu2.score = 58stu1.introduce()stu1.is_passed()stu2.introduce()stu2.is_passed()

输出结果:

我叫张三,今年18岁,考试得了95分张三 已经及格了我叫李四,今年19岁,考试得了58分李四 没有及格

这个例子很有代表性。

同一个类 两个不同对象 相同的方法 不同的属性值 不同的输出结果

只要你把这一段真正看懂,实例属性和实例方法的关系基本就通了。

十七、实例属性和实例方法,最好成对理解

你不要把它们拆开记。

因为单独记属性,很容易变成“哦,对象里存点数据”。 单独记方法,又容易变成“哦,类里放几个函数”。

真正应该建立起来的感觉是:

实例属性负责保存状态,实例方法负责操作状态。

比如一个学生对象:

属性保存姓名、年龄、成绩 方法负责介绍自己、判断是否及格

比如一个银行账户对象:

属性保存账号、余额 方法负责存钱、取钱、查看余额

只要这个感觉起来了,面向对象就不再是语法堆砌,而是在组织现实角色。

十八、这一章最常见的几个误区

先帮你提前避开几个坑。

第一个误区,把实例属性当成类统一的数据。 不是的,实例属性属于每个对象自己。

第二个误区,觉得方法只是普通函数换个位置。 不完全是。实例方法通常会和对象自己的属性发生关系。

第三个误区,看见 self 就慌。 你现在先把它理解成“当前对象自己”就够用了。

第四个误区,以为对象创建出来就自动有所有属性。 不是。你如果没有赋值,属性就可能还不存在。

这些坑现在先绕开,后面会轻松很多。

十九、本章小练习

你可以自己做两个很适合巩固的小练习。

第一个练习,定义一个 Book 类。

要求:

有 title、author、price 三个实例属性 有一个 show_info() 方法,输出这本书的信息

参考写法:

classBook:defshow_info(self):        print(f'书名:{self.title},作者:{self.author},价格:{self.price}元')book1 = Book()book1.title = 'Python 入门'book1.author = '小王'book1.price = 59book2 = Book()book2.title = '数据分析实战'book2.author = '老李'book2.price = 88book1.show_info()book2.show_info()

第二个练习,定义一个 Phone 类。

要求:

有 brand、battery 两个实例属性 有一个 charge() 方法,每次调用让电量加 10,并输出当前电量

参考写法:

classPhone:defcharge(self):        self.battery = self.battery + 10        print(f'{self.brand} 当前电量是 {self.battery}%')phone1 = Phone()phone1.brand = '华为'phone1.battery = 50phone1.charge()phone1.charge()

这两个练习都非常典型。 一个练“属性展示”,一个练“方法修改属性”。 你把它们跑通,感觉会非常扎实。

二十、本章总结

这一章是面向对象阶段里非常关键的一章。

实例属性,是某个具体对象自己拥有的数据。 实例方法,是某个具体对象可以执行的行为。 不同对象虽然来自同一个类,但可以拥有不同的属性值。 同一个实例方法作用在不同对象上时,也会因为属性不同而产生不同结果。 方法里的 self,你现在可以先理解成“当前对象自己”。 实例方法不仅可以读取对象属性,也可以修改对象属性。 属性和方法最好放在一起理解:属性负责保存状态,方法负责操作状态。

到这里,你已经真正摸到面向对象的门把手了。 下一章我们继续讲最重要的一个方法:074|init 方法详解:对象创建时到底发生了什么。

最新文章

随机文章