构造方法
大家好,这个章节我们来介绍一下类中的构造方法。
简介
在上一章节中,通过动态绑定的方式为实例对象添加了属性。
但是这种操作显然是不符合逻辑的。每个实例对象一旦被实例化,就应该含有类中定义的属性。
此时就需要使用构造方法来实现。
在之前的章节中,我们学到过如何通过动态绑定给实例对象添加属性。这个方式虽然能用,但存在一些问题,比如每个对象实例创建时,属性并不会立刻绑定,而是需要手动赋值。显然,这样的做法不符合逻辑,因为每个实例一旦被创建,就应该自动包含类中定义的属性,这时候就需要引入构造方法来解决这个问题。构造方法的作用就是,在实例对象创建时,自动为该对象赋予属性,不需要手动去绑定。
构造方法
构造方法 init(self) 在实例对象时自动调用, self 参数不需要手动传参,该参数在实例对象时,由解释器自动传入被实例的对象。
此时,还不能定义属性,构造方法本质上就是一个具有特殊意义的函数,而在函数中直接定义变量不是属性,而是函数内的局部变量。
class Student:
def __init__(self):
print("Init Run ...")
s1 = Student()
s2 = Student()
接下来,我们看一下构造方法。构造方法是一个特殊的方法,在实例化对象时会自动调用。它的名字是 init,作用就是初始化对象的属性。特别注意,init 方法的第一个参数是self,这个self参数不需要我们手动传递,它是由Python解释器自动传入的,表示当前正在被创建的对象。构造方法的作用就像是创建对象时的“初始化程序”,但它本身并不是用来定义属性的。比如你在构造方法中写一些代码,虽然它在方法体内,但这些并不会成为对象的属性,它们只是方法内部的局部变量。在这个例子中,我们只是简单地在构造方法里输出了一个提示信息,这个信息会在每次创建对象时被自动调用。你会看到,当我们创建了两个学生对象Student时,构造方法都会被执行一次。
self
self 是一个特殊的关键字,用来表示当前被实例的对象,可以理解为人称代词我。
通过 self 可以定义或访问实例对象的属性或方法。
格式:self.属性名 = 值
class Student:
def __init__(self):
self.name = "Tom"
self.age = 22
s1 = Student()
s2 = Student()
print(s1.name)
print(s1.age)
print(s2.name)
print(s2.age)
在构造方法中,有一个关键字叫做self,它是指当前正在实例化的对象。你可以把它看作“我”或“自己”。在方法内部,它代表了当前对象本身。通过self,我们可以访问或定义当前实例的属性或方法。比如,我们在构造方法里初始化了对象的name和age属性:这段代码中,我们创建了两个学生对象s1和s2,它们的name和age属性分别都被初始化为"Tom"和22。通过self,我们在构造方法中为每个对象赋予了这两个属性。这里有一个小问题,如果我们给所有实例的属性都设置了相同的值,那这些值对于每个实例对象来说就不够“独立”了,这个问题稍后我们会讨论。
通过 构造方法 和 self ,实现了为实例对象定义属性,其本质上还是为实例对象动态绑定属性,只是动态绑定的时机变了,从实例完对象再绑定属性,变成了在自动调用执行的构造方法中进行动态绑定。
并且,从上面的代码中还发现另外一个问题,就是所有实例的对象出来,都有共同的属性值,这显然也是不符合逻辑的。
通过构造方法和self,我们成功地为实例对象定义了属性。实际上,这和之前通过动态绑定赋值的方式类似,不过构造方法是让我们在创建对象时自动进行属性绑定。注意,构造方法本质上还是通过self来动态绑定属性的,只不过它的调用时机发生了变化:从对象创建后手动绑定,变成了在对象创建时就由构造方法自动进行绑定。
带参构造方法
构造方法也可以携带参数,根据类中属性的定义,传入对应的参数对实例属性进行实始化。
格式: __init__(self, args....)
以下示例,通过构造方法,实例了真正的对象。
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
s1 = Student("Tom", 22)
s2 = Student("Jack", 23)
print(s1.name)
print(s1.age)
print(s2.name)
print(s2.age)
接下来,我们来看看带参构造方法。构造方法不一定只能简单地初始化固定的属性,它还可以接受外部传入的参数,这样就可以在创建对象时动态地设置对象的属性值。在这个例子中,我们为构造方法添加了两个参数name和age,在创建学生对象时,我们传入了这些参数。这样每个学生对象就能拥有不同的name和age属性,而不再是每个学生都是“Tom”和22岁。这也解决了我们前面提到的问题:每个对象都应该有自己独立的属性值,而不是所有对象共享相同的属性值。
__str__(self) 方法
在实例对象后,如果直接打印对象,输出该对象的相关信息,发现实际输出的并不是想要的结果。而是该实例对象的类型和地址。
如果想在输出实例对象时,按指定的格式输出,需要实现 str(self) 方法。
该方法不接收除 self 以外的参数,self 参数自动传入,函数只能返回一个字符串。
class Student:
def __init__(self,name, age):
self.name = name
self.age = age
def __str__(self):
return f"Name: {self.name} -- Age: {self.age}"
s1 = Student("Tom", 22)
s2 = Student("Jack", 23)
print(s1)
print(s2)
接下来,我们再介绍一个特殊的方法。当你直接打印一个对象时,Python 默认输出的是对象的类型和内存地址。比如,你想打印一个学生对象的相关信息时,结果可能是这个对象的内存地址。显然,这对用户来说并不直观。为了定制对象的输出格式,我们可以在类中实现一个 str 方法。这个方法会返回一个字符串,当你打印对象时,Python会自动调用这个方法来获取你希望显示的信息。这段代码中,我们定义了 str 方法,当我们打印s1和s2时,它们会输出:Name: Tom -- Age: 22和Name: Jack -- Age: 23,而不是内存地址。这样我们就能按我们指定的格式显示对象的属性信息。
总结
- 构造方法
self- 带参构造方法
__str__(self)方法
最后我们来总结一下。构造方法 init 是用来初始化对象的属性的。self是一个特殊的参数,代表当前正在被实例化的对象,所有对象的属性都通过self来定义。我们可以通过带参构造方法来在实例化时传入不同的属性值。str 方法用来定制对象打印时的输出格式。这些知识点是面向对象编程的核心内容,让我们能够创建更符合逻辑的类和对象,并且能够灵活地控制对象的初始化和输出。