上一章我们已经知道,对象之所以能“各有各的数据”,靠的是实例属性。
比如你已经会写:
classStudent:defintroduce(self): print(f'我叫{self.name},今年{self.age}岁,成绩是{self.score}分')stu1 = Student()stu1.name = '张三'stu1.age = 18stu1.score = 95
这种写法能不能用?当然能。 而且对理解实例属性非常有帮助。
但你很快就会发现,它有两个明显问题。
第一,麻烦。 每创建一个对象,都要手动一条一条补属性。
第二,不稳。 如果你忘了给某个属性赋值,方法一调用,就可能直接报错。
比如你只写了:
stu1 = Student()stu1.name = '张三'
但没有写 age 和 score,这时候去调用 introduce(),程序就容易出问题。
所以,面向对象里很快就要引出一个特别重要的方法:
__init__
这一章,我们就把它彻底讲清。
一、先说结论,init 是干什么的
你先别急着看复杂解释,先记一句最实用的话:
__init__ 是对象创建时自动执行的初始化方法。
什么叫初始化?
你可以理解成:
对象刚刚被创建出来时,顺手把它该有的数据准备好。
也就是说,以前你是这样干的:
先创建对象 再手动一个个补属性
现在有了 __init__ 以后,可以变成:
创建对象的同时,把属性直接准备好
这就是它最核心的价值。
二、为什么对象创建时需要一个专门的方法
因为现实里的很多对象,刚一出生就应该带着基本信息,而不是先空着。
比如一个学生对象,正常情况下至少应该有:
姓名 年龄 成绩
比如一个汽车对象,通常也应该有:
品牌 颜色 价格
如果对象刚创建出来时完全是空壳子,后面再零零碎碎补,既麻烦,也容易漏。
所以 __init__ 的作用,本质上就是:
规定对象在出生那一刻,应该先拥有哪些基本属性。
你可以把它理解成“对象的出生流程”。
三、先看最基本的写法
__init__ 的基本结构长这样:
class 类名:def__init__(self): 初始化代码
比如:
classStudent:def__init__(self): print('一个学生对象被创建了')
然后创建对象:
stu1 = Student()
运行后会输出:
一个学生对象被创建了
这就说明,__init__ 不需要你手动调用。 只要你执行了:
Student()
对象一创建,__init__ 就会自动执行。
这一点非常关键。
四、为什么它叫双下划线 init 双下划线
你可能已经注意到了,这个名字长得有点特殊:
__init__
前后各有两个下划线。
这种名字在 Python 里通常表示一种特殊方法。 你现在不用一下子研究所有特殊方法,只要先记住:
__init__ 是 Python 约定好的初始化方法名字。
它不是你随便起的。 你写成别的名字,比如:
definit(self):
那就不是这个效果了,创建对象时也不会自动执行。
所以这里一定要记准确。
五、对象创建时,到底发生了什么
这一章的标题就要回答这个问题。
当你写:
stu1 = Student()
表面上看,好像只是在“创建一个对象”。 但实际上,背后至少发生了两件事。
第一,Python 先帮你创建出一个新的 Student 对象。 第二,创建完成后,自动执行这个类里的 __init__ 方法。
所以更准确地说:
Student() 不只是“造对象”, 还是“造完对象后,顺手做初始化”。
这就是为什么我们说,__init__ 是对象创建时自动执行的初始化方法。
你现在只要把这条主线抓住,后面很多细节都会顺。
六、真正实用的写法,是在 init 里给属性赋值
前面那个打印一句话的例子,只是为了让你感受到自动执行。 真正高频的用法,是在 __init__ 里给对象设置初始属性。
比如:
classStudent:def__init__(self): self.name = '张三' self.age = 18 self.score = 95defintroduce(self): print(f'我叫{self.name},今年{self.age}岁,成绩是{self.score}分')
然后创建对象并调用方法:
stu1 = Student()stu1.introduce()
输出结果:
我叫张三,今年18岁,成绩是95分
这里最关键的地方是:
self.name = '张三'self.age = 18self.score = 95
这说明,__init__ 非常适合做“对象刚创建时的属性准备工作”。
七、但这样写还有一个问题
你可能立刻就会发现,刚才这个写法虽然比手动补属性规范了一点,但它还是不够灵活。
因为现在每创建一个学生对象,默认都是:
张三 18 岁 95 分
那如果我想要创建李四、王五怎么办?
总不能每次都改类里的代码吧。
所以真正更常用的写法,是让 __init__ 接收参数。
也就是说:
创建对象时,把不同数据传进去。__init__ 再把这些数据装到对象自己身上。
这一步一出来,面向对象才真正顺起来。
八、最常见的 init 写法:带参数初始化
看下面这个版本:
classStudent:def__init__(self, name, age, score): self.name = name self.age = age self.score = scoredefintroduce(self): print(f'我叫{self.name},今年{self.age}岁,成绩是{self.score}分')
创建对象时这样写:
stu1 = Student('张三', 18, 95)stu2 = Student('李四', 19, 88)stu1.introduce()stu2.introduce()
输出结果:
我叫张三,今年18岁,成绩是95分我叫李四,今年19岁,成绩是88分
这段代码非常非常重要。
因为从这里开始,你已经进入了类最常见、最标准的使用方式。
九、这一行到底在干什么
很多新手第一次看到下面这句时,会有点晕:
self.name = name
其实你把它翻译成人话就行:
把传进来的 name,存到这个对象自己的 name 属性里。
再看一遍:
def__init__(self, name, age, score): self.name = name self.age = age self.score = score
左边的:
self.nameself.ageself.score
表示对象自己的属性。
右边的:
nameagescore
表示创建对象时传进来的参数。
所以这一段代码,本质上就是在做属性绑定。
你可以把它想成:
外面传数据进来 对象自己收下并保存
十、创建对象时传参数,和调用函数很像
这个地方你可以借用前面学函数的理解。
比如普通函数你会写:
defadd(a, b):return a + b
调用时:
add(3, 5)
而现在类里写的是:
def__init__(self, name, age, score): ...
创建对象时:
Student('张三', 18, 95)
是不是有点像?
没错,本质上它就是在传参数。 只不过这里不是在调用普通函数,而是在创建对象时把参数交给 __init__ 去处理。
所以你不要把 __init__ 想得太神秘。 它首先是一个方法,然后碰巧在对象创建时自动被调用。
十一、为什么有了 init 以后,代码会整洁很多
对比一下两种写法。
第一种,手动补属性:
classStudent:defintroduce(self): print(f'我叫{self.name},今年{self.age}岁,成绩是{self.score}分')stu1 = Student()stu1.name = '张三'stu1.age = 18stu1.score = 95
第二种,使用 __init__:
classStudent:def__init__(self, name, age, score): self.name = name self.age = age self.score = scoredefintroduce(self): print(f'我叫{self.name},今年{self.age}岁,成绩是{self.score}分')stu1 = Student('张三', 18, 95)
显然,第二种更集中,也更规范。
创建对象时,该有的数据一次给齐。 对象一出生就是完整状态。 后面的方法也更放心使用这些属性。
这就是 __init__ 最大的实战价值。
十二、为什么说 init 让对象从“空壳”变成“成品”
如果没有 __init__,对象刚创建出来,往往只是一个空壳子。
比如:
stu1 = Student()
这时候它可能什么属性都没有。 你还得手动补。
但有了 __init__ 以后:
stu1 = Student('张三', 18, 95)
对象一创建,姓名、年龄、成绩就都准备好了。
这就像生产线一样。
以前是先造一个空盒子,再手工往里塞东西。 现在是出厂时就已经配齐。
所以 __init__ 的本质,其实就是让对象更像一个完整成品,而不是半成品。
十三、一个更贴近现实的例子:汽车类
我们再看一个汽车例子:
classCar:def__init__(self, brand, color, price): self.brand = brand self.color = color self.price = pricedefshow_info(self): print(f'这辆车的品牌是{self.brand},颜色是{self.color},价格是{self.price}元')
创建对象:
car1 = Car('比亚迪', '白色', 120000)car2 = Car('特斯拉', '黑色', 260000)car1.show_info()car2.show_info()
输出结果:
这辆车的品牌是比亚迪,颜色是白色,价格是120000元这辆车的品牌是特斯拉,颜色是黑色,价格是260000元
这段代码已经非常接近真实开发中的类使用方式了。
类定义共同结构。__init__ 负责初始化对象数据。 方法负责利用对象数据执行行为。
十四、如果传参个数不对,会怎么样
这点你一定要提前有意识。
比如类是这样定义的:
classStudent:def__init__(self, name, age, score): self.name = name self.age = age self.score = score
那么创建对象时,就应该传三个参数:
stu1 = Student('张三', 18, 95)
如果你少传一个:
stu1 = Student('张三', 18)
或者多传一个:
stu1 = Student('张三', 18, 95, '男')
程序就会报错。
为什么?
因为 __init__ 已经规定好了对象初始化时需要哪些数据。 你传得不对,程序自然没法按预期完成初始化。
这也说明了一件事:
__init__ 不只是赋值工具,它也在规定对象创建时的数据要求。
十五、init 里除了赋值,还能做别的事吗
能。
虽然最常见的用法是给属性赋值,但你也可以在里面写一些初始化相关的逻辑。
比如:
classUser:def__init__(self, username): self.username = username print(f'用户 {self.username} 已创建')
创建对象时:
u1 = User('admin')
输出:
用户 admin 已创建
再比如可以做简单计算:
classRectangle:def__init__(self, width, height): self.width = width self.height = height self.area = width * height
这说明,__init__ 不只是存数据,也可以顺手做一些和初始化有关的准备动作。
不过初学阶段,你先把重点放在“设置属性”上就够了。
十六、init 不是返回对象的方法
这是个特别容易误解的点。
有些新手会下意识觉得,既然对象创建时会执行 __init__,那是不是它负责“返回对象”。
你现在先不用钻太深底层,只要记住一个实用结论:
__init__ 的主要职责是初始化对象,不是负责把对象造出来。
对象创建这件事,本身是 Python 在做。__init__ 是在对象已经创建出来之后,继续负责给它准备初始状态。
所以你通常不会在 __init__ 里写什么返回值。 它不是普通函数意义上的“加工后返回结果”。
这点先有印象就够,后面你会越来越自然。
十七、再看一个学生类完整例子
下面这个例子建议你亲手敲一遍。
classStudent:def__init__(self, name, age, score): self.name = name self.age = age self.score = scoredefintroduce(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('张三', 18, 95)stu2 = Student('李四', 19, 58)stu1.introduce()stu1.is_passed()stu2.introduce()stu2.is_passed()
输出结果:
我叫张三,今年18岁,成绩是95分张三 已经及格了我叫李四,今年19岁,成绩是58分李四 没有及格
这个例子已经把前几章的核心内容真正串起来了。
类 对象 实例属性 实例方法__init__
一旦你能顺手写出这种代码,说明你已经真正开始掌握面向对象了。
十八、为什么这章之后,类会突然顺很多
因为 __init__ 解决了一个最关键的问题:
对象的数据,到底该什么时候准备好。
前一章你已经知道,属性是对象自己的数据。 但没有 __init__ 时,属性像是后补进去的。 而有了 __init__ 以后,属性的归属、来源、创建时机,一下就清楚了。
也就是说,__init__ 把对象创建这件事正式规范起来了。
从这一章开始,你写类才真正开始像“正常的类写法”。
十九、本章小练习
你可以做两个很适合巩固的练习。
第一个练习,定义一个 Book 类。
要求:
通过 __init__ 接收 title、author、price有一个 show_info() 方法,输出图书信息
参考代码:
classBook:def__init__(self, title, author, price): self.title = title self.author = author self.price = pricedefshow_info(self): print(f'书名:{self.title},作者:{self.author},价格:{self.price}元')book1 = Book('Python 入门', '小王', 59)book2 = Book('数据分析实战', '老李', 88)book1.show_info()book2.show_info()
第二个练习,定义一个 Phone 类。
要求:
通过 __init__ 接收 brand 和 battery有一个 charge() 方法,每次调用电量加 10
参考代码:
classPhone:def__init__(self, brand, battery): self.brand = brand self.battery = batterydefcharge(self): self.battery = self.battery + 10 print(f'{self.brand} 当前电量是 {self.battery}%')phone1 = Phone('华为', 50)phone1.charge()phone1.charge()
这两个练习一个练初始化属性,一个练方法修改属性,非常适合把这章内容落下来。
二十、本章总结
这一章你真正拿下了面向对象里最关键的一块内容之一。
__init__ 是对象创建时自动执行的初始化方法。 它最常见的作用,是在对象创建时给实例属性赋初值。 有了它以后,对象不再是空壳子,而是一出生就带着完整数据。 创建对象时传入的参数,会交给 __init__ 去处理。self.name = name 这种写法,本质上就是把传进来的值保存到对象自己的属性里。__init__ 不负责“返回对象”,它负责的是“初始化对象”。 从这一章开始,类的写法才真正进入最常见、最规范的形态。
下一章我们继续把一个让无数新手卡住的问题彻底讲清:075|self 到底是谁:新手最常见疑惑彻底讲清。