65. __init__
方法
文章目录
- 65. `__init__`方法
- 1. 知识回顾在类的方法中调用类的属性
- 2. 知识回顾调用方法时传值
- 3.体验`__init__`方法
- 4. `__init__`的作用
- 5.` __init__`方法的写法
- 6. `__init__`方法调用类的属性
- 7. 课堂实操
1. 知识回顾在类的方法中调用类的属性
【目标任务】
创建一个类,计算2个数的和。
【体验代码】
# 定义一个求和类,类名为Sum
class Sum:
# 直接写在类里的变量称为类属性
x = 2
y = 4
# 在类中定义的函数称为方法
# 方法名为qiuhe,功能是计算类里2个变量的和
def qiuhe(self):
# 方法中的代码块
print(x+y)
# 创建对象:对象名=类名( )
he= Sum( )
# 调用对象:对象名.方法名(值)
he.qiuhe( )
运行上述的代码程序报错,提示name 'x' is not defined
即x没有被定义。
观察代码的第5和第6行,我已经给变量赋值了。
# 直接写在类里的变量称为类属性
x = 2
y = 4
但程序还是提示没有被定义,这是因为x
和y
是在类里定义的变量。
在类里定义的变量我们称之为类属性。
上节课我们学过,在类内部的方法中调用类的属性或其它类的方法时,需要在前面加上slef. 如:
self.属性名
self.方法名
# 在类中定义的函数称为方法
# 方法名为qiuhe,功能是计算类里2个变量的和
def qiuhe(self):
# 方法中的代码块
print(x+y)
qiuhe
是在类中定义的方法。
x和y是类里的属性。
要调用类里的属性,语法为self.属性名。
因此我们将代码的第12行:
# 方法中的代码块
print(x+y)
更改如下:
# 方法中的代码块
print(self.x+self.y)
【综合代码】
# 定义一个求和类,类名为Sum
class Sum:
# 直接写在类里的变量称为类属性
x = 2
y = 4
# 在类中定义的函数称为方法
# 方法名为qiuhe,功能是计算类里2个变量的和
def qiuhe(self):
# 方法中的代码块
print(self.x+self.y)
# 创建对象:对象名=类名( )
he= Sum( )
# 调用对象:对象名.方法名(值)
he.qiuhe()
【终端输出】
6
输出结果为6,我们成功设计了一个求和的小程序。
但这个程序只能计算2和4的和,不方便用户。
用户如果需要计算其他2个数的和,就要更改类的属性。
我们使用类的优势之一在于,代码写好后我们将它封装保存,需要的时候我们直接调用它就好。
因此,我们最好不要取修改类里的代码。
那怎么优化呢?
我们可以通过调用方法时传值的形式进行代码优化。
2. 知识回顾调用方法时传值
# 定义一个求和类,类名为Sum
class Sum:
# 在类中定义的函数称为方法
# 方法名为qiuhe,功能是计算类里2个变量的和
def qiuhe(self,x,y):
# 方法中的代码块
print(x+y)
# 创建对象:对象名=类名( )
he= Sum( )
# 调用对象:对象名.方法名(值)
he.qiuhe(2,4)
【终端输出】
6
和之前的代码相比,我做了如下改动:
- 我把类定义属性的语句删除了。
# 直接写在类里的变量称为类属性
x = 2
y = 4
- 我修改了求和方法的参数。
将原来的:
def qiuhe(self):
# 方法中的代码块
print(self.x+self.y)
修改为:
# 在类中定义的函数称为方法
# 方法名为qiuhe,功能是计算类里2个变量的和
def qiuhe(self,x,y):
# 方法中的代码块
print(x+y)
和之前的方法相比,我在方法中增加了2个参数,x和y。
最后再调用方法的时候直接传入方法中需要的值。
# 调用对象:对象名.方法名(值)
he.qiuhe(2,4)
方法中的值是按位置进行传递的。
2传递给x。
4传递给y。
方法传值的优势在于不管你想计算哪两个数的和,只需要修改方法中的值即可。
【体验代码】
观察下面的代码,只用修改值我们就可成功计算出多个两位数的和。
# 定义一个求和类,类名为Sum
class Sum:
# 在类中定义的函数称为方法
# 方法名为qiuhe,功能是计算类里2个变量的和
def qiuhe(self,x,y):
# 方法中的代码块
print(x+y)
# 创建对象:对象名=类名( )
he= Sum( )
# 调用对象:对象名.方法名(值)
he.qiuhe(2,4)
he.qiuhe(4,4)
he.qiuhe(7,4)
【终端输出】
6
8
11
3.体验__init__
方法
我们还可以继续优化我们的代码:
观察下面的代码,重点注意观察第6行。
# 定义一个求和类,类名为Sum
class Sum:
# 在类中定义的函数称为方法
# 方法名为__init__
def __init__(self,x,y):
# 方法中的代码块
print(x+y)
# 创建对象:对象名=类名( )
he= Sum(2,4)
【终端输出】
6
上面的代码较之前的代码,我做了如下几个调整:
- 把之前的函数名
qiuhe
修改为__init__
下面是之前的旧代码:
# 定义一个方法,计算类里2个变量的和
def qiuhe(self,x,y):
# 方法中的代码块
print(x+y)
下面是修改后的代码:
def __init__(self,x,y):
# 方法中的代码块
print(x+y)
- 把要传递的值放入创建对象的语句里,删除了调用方法的代码。
之前的旧代码,有调用方法语句,传入的值在调用方法语句里。
# 创建对象:对象名.类名( )
he= Sum( )
# 调用对象:对象名.方法名(值)
he.qiuhe(2,4)
现在的代码只有创建对象语句,传入的值在创建对象语句里。
# 创建对象:对象名=类名(值)
he= Sum(2,4)
之前说过,要输出类方法里的语句,是需要一个调用方法的语句的。
那为什么这里修改方法名后,不调用也能输出呢。
那是因为__init__
方法的作用就是,在类创建对象时,不需要调用方法语句,就可以自动执行__init__
方法中的代码块(这是我自己对该方法的解释,仅供参考)。
大家可以试一下,同样的情况下,如果方法名不为__init__
,程序是会报错的:
# 定义一个求和类,类名为Sum
class Sum:
# 在类中定义的函数称为方法
def qiuhe(self,x,y):
# 方法中的代码块
print(x+y)
# 创建对象:对象名=类名( )
he= Sum(2,4)
【终端输出】
TypeError: Sum() takes no arguments
运行上述代码,程序报错,提示Sum() takes no arguments
即Sum不接受参数。
同样的代码,方法名不一样,输出结果就不一样,这就是__init__
方法在作怪。
4. __init__
的作用
Python本身有内置函数和自定义函数两种。
自定义函数我们可以根据自己的喜好命名。
但内置函数就不能随便更改名字。只有单词拼写正确了,我们才能使用该函数本身具有的功能。例如type、input、print函数。
其实类中也可以这样理解。
上节课我用的drive ,stop,back都是我自己定义的方法名。
这里的 __init__
我们可以理解成它是类中的内置方法,方法名是固定的。
init是initialization的缩写。
initialization [ɪˌnɪʃəlaɪ’zeɪʃn] :初始化。
__init__
方法通常称为初始化方法。
__init__
方法的作用官方解释是支持带参数类的初始化,声明该类的属性(类中的变量)。
如果你是小白,这样的话术很难理解。
那我们可以这样理解它:
类中的属性不是一成不变的,是一个可能会变化的值。
我们不想在类中定义属性,而想在创建对象时传入,这时可以用init方法在类中声明属性即类里的变量。
当然我还有一种简单粗暴的理解。
你就把它当做一个类中的普通方法,这个方法有以下几个作用:
1. init方法接收创建对象时传入的值。
2. init方法中的代码块不需要调用语句,创建对象就会被自动执行。
【举例说明】
class Test:
def __init__ (self):
print("只要有创建对象语句,我就会被输出。")
def A(self):
print("要调用方法A,我才输出。")
# 创建对象:对象名=类名( )
ceshi= Test( )
【终端输出】
只要有创建对象语句,我就会被输出。
上述代码因为只有创建对象语句,没有调用方法语句。
因此,下面这个语句被输出了,因为init方法中的代码块会自动被执行。
print("只要有创建对象语句,我就会被输出。")
下面的语句没有输出,因为没有调用方法A。
print("要调用方法A,我才输出。")
【增加一个调用方法A的语句】
class Test:
def __init__ (self):
print("只要有创建对象语句,我就会被输出")
def A(self):
print("要调用方法A,我才输出。")
# 创建对象:对象名=类名( )
ceshi= Test( )
# 调用方法:对象名.方法名
ceshi.A()
【终端输出】
只要有创建对象语句,我就会被输出
要调用方法A,我才输出。
两句话都被输出了,因为我增加了调用方法A的语句,如下:
# 调用方法:对象名.方法名
ceshi.A()
5. __init__
方法的写法
定义__init__
方法的语法和定义其它方法的语法是一样的。
有两个需要特别注意的地方。
-
方法名是
init
,很多初学者容易错写成int
。 -
方法名前后格有2条小横线,注意是前面2条,后面2条,总的4条。初学者易写成2条小横线。
6. __init__
方法调用类的属性
这是我刚才写的代码:
# 定义一个求和类,类名为Sum
class Sum:
# 在类中定义的函数称为方法
# 方法名为__init__
def __init__(self,x,y):
# 方法中的代码块
print(x+y)
# 创建对象:对象名=类名( )
he= Sum(2,4)
上述的代码运行虽然没有错误,但其实是不规范的。
下面的代码是规范的:
# 定义一个求和类,类名为Sum
class Sum:
# 在类中定义的函数称为方法
# 方法名为__init__
def __init__(self,x,y):
self.x = x
self.y = y
# 方法中的代码块
print(self.x+self.y)
# 创建对象:对象名=类名( )
he= Sum(2,4)
【终端输出】
6
我是这样理解的,仅供大家参考:
2和4是在创建对象时传入的值,理论上等同于类的属性。
是类的属性,在类中调用类的属于就需要用self.属性名。
上述方法有self,x,y三个参数。
self.x
中的x表示的是类的属性。
等号后面的x表示的是值。
self.属性=值
self.x = x
self.y = y
按照位置,2传递给x。self.x相当于类里的变量x。
按照位置,4传递给y。self.y相当于类里的变量y。
按照语法规则在init中我们是要带着self
.走的。
但没有目前也没有报错。
至于为什么没报错,或者self.
在这里存在的意义我目前还没有语言给大家解释清楚。
但建议所有学者都带上self.
,我相信存在既有意义,只是我水平不够,解释不清楚。
7. 课堂实操
下面是我们上节课生产各种汽车的代码:
# 定义一个车类,类名为Cars
class Cars:
# 直接写在类里的变量称为类属性
color_1 = "红色"
color_2 = "黑色"
color_3 = "黄色"
color_4 = "绿色"
type_1 = "小轿车"
type_2 = "越野车"
type_3 = "公交车"
type_4 = "跑车"
# 在类中定义的函数称为方法
# 方法的第1个参数必须是slef
def drive(self, speed):
# 方法中的代码块
print(f"经测试,{self.color_4}的{self.type_4}的最高时速是{speed}公里每小时。")
print("经测试,{}的{}的最高时速是{}公里每小时。".format(self.color_2, self.type_4, speed))
print("经测试,{}的{}的最高时速是{}公里每小时。".format(self.color_1, self.type_4, speed))
# 创建对象:对象名=类名( )
paoche = Cars( )
# 调用对象:对象名.方法名(值)
# 测试车速
paoche.drive(230)
【终端输出】
经测试,绿色的跑车的最高时速是230公里每小时。
经测试,黑色的跑车的最高时速是230公里每小时。
经测试,红色的跑车的最高时速是230公里每小时。
下面,我对上面的代码就行优化:
# 定义一个车类,类名为Cars
class Cars:
# 使用初始化方法init
def __init__(self, color, type, speed):
self.color = color
self.type = type
self.speed =speed
# 方法中的代码块
print(f"经测试,{self.color}的{self.type}的最高时速是{self.speed}公里每小时。")
# 创建对象:对象名=类名( )
che = Cars("红色","公交车",160 )
che = Cars("黑色","跑车",280 )
che = Cars("黄色","卡车",180 )
che = Cars("紫色","小轿车",240)
che = Cars("黑色","小轿车",240)
che = Cars("红色","小轿车",240)
che = Cars("绿色","小轿车",240)
【终端输出】
经测试,红色的公交车的最高时速是160公里每小时。
经测试,黑色的跑车的最高时速是280公里每小时。
经测试,黄色的卡车的最高时速是180公里每小时。
经测试,紫色的小轿车的最高时速是240公里每小时。
经测试,黑色的小轿车的最高时速是240公里每小时。
经测试,红色的小轿车的最高时速是240公里每小时。
经测试,绿色的小轿车的最高时速是240公里每小时。
对比2段代码,大家应该能感受到init方法的优势了。
终端输出了7个语句,即生产了7种汽车。
如果我们没有用init方法,要输出上面的这7个语句。
我们需要定义7个颜色变量,7个汽车类型变量,7个汽车时速变量,写7带字符串格式化的输出语句。
而用init方法,代码就相对简洁了很多。