Python Python 中的构造函数 init 是如何工作的?
Python 中的构造函数 init 是一个非常重要的概念,在对象创建时自动执行。即便在没有明确定义构造函数的情况下,Python 也会自动创建一个没有参数的构造函数,因为每个对象都需要进行初始化工作。
阅读更多:Python 教程
什么是构造函数?
在 Python 中,构造函数是一种特殊的方法,它在对象被创建之后自动调用。构造函数的任务是初始化对象。它通常命名为 init(注意:前后各两个下划线)。Python 中的所有对象都有构造函数,无论你是否显式地定义了它。你可以通过定义自己的构造函数来为对象指定初始状态。
当你使用类来创建一个新的对象时,Python 会自动调用 init 函数,并将该对象作为第一个参数传递给它。你可以在 init 函数中对该对象初始化,以确保它具有适当的初始状态。
下面是一个简单的示例,我们定义一个类,构造函数接受两个参数,并将它们分别赋值给对象的属性 x 和 y:
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
p = Point(1, 2)
print(p.x, p.y) # Output: 1 2
在上面的代码中,我们定义了一个 Point 类,并在构造函数 init 中初始化 x 和 y。我们创建了一个名为 p 的对象,并将其 x 和 y 分别设置为 1 和 2。最后,我们打印了对象的 x 和 y 属性值。
实例变量和类变量
在 Python 中,有两种类型的变量:实例变量和类变量。实例变量是对象的属性,每个对象都有自己的副本。类变量是共享的,它们属于类而不是任何特定的实例。
实例变量是在构造函数中初始化的,它们只对特定的实例可见。我们可以通过使用 self 关键字将变量绑定到对象上。
类变量是在类定义中初始化的,它们对所有实例都是相同的。我们可以通过在类中定义变量来创建类变量,并且可以通过使用类名来引用它们。
下面是一个示例程序,我们定义一个类并创建两个对象。在构造函数中,我们初始化了实例变量 x 和 y。我们还定义了一个类变量 count,用于跟踪 Point 的实例数:
class Point:
count = 0
def __init__(self, x=0, y=0):
self.x = x
self.y = y
Point.count += 1
p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1.x, p1.y) # Output: 1 2
print(p2.x, p2.y) # Output: 2 3
print(Point.count) # Output: 2
在上面的代码中,我们使用 Point.count 访问类变量 count。在每次创建 Point 对象时,我们都会将计数器 count 的值增加1。
参数传递
在构造函数中,我们可以接受一个或多个参数,并使用它们来初始化对象。Python 中的构造函数可以使用位置参数,也可以使用关键字参数。对于每个参数,你可以指定默认值,如果调用时未提供该参数,则将使用默认值。
下面是一个示例,我们定义一个类,并在构造函数 init 中接受一个位置参数和一个关键字参数。
class Call:
def __init__(self, phone, name='Unknown'):
self.phone = phone
self.name = name
call1 = Call('+123456', 'Tom')
call2 = Call('+7891011')
print(call1.phone, call1.name) # Output: ('+123456', 'Tom')
print(call2.phone, call2.name) # Output: ('+7891011', 'Unknown')
在上面的代码中,我们创建了 Call 类,并在构造函数 init 中使用了一个位置参数 phone 和一个关键字参数 name。如果调用时未提供 name 参数,则将使用默认值 ‘Unknown’。
我们创建了两个 Call 对象,一个指定了 name 参数,一个未指定。在打印对象时,我们将输出对象的 phone 和 name 属性。
继承和多态
Python 中的类可以继承自另一个类,这意味着子类将从另一个类继承所有方法和属性。这样可以使代码更简单和可重用。
下面是一个示例程序,我们定义了一个名为 Animal 的基类,和它的两个派生类 Dog 和 Cat。我们在 Animal 类中定义了一个 make_sound() 方法,让子类重写它。
class Animal:
def __init__(self, name):
self.name = name
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
print(self.name + ' says Woof!')
class Cat(Animal):
def make_sound(self):
print(self.name + ' says Meow!')
d = Dog('Fido')
c = Cat('Fluffy')
d.make_sound() # Output: Fido says Woof!
c.make_sound() # Output: Fluffy says Meow!
在上面的代码中,我们首先定义了一个 Animal 类,并在该类中定义了一个 make_sound() 方法。我们还定义了两个继承自 Animal 类的子类,Dog 和 Cat。我们在每个子类中重写了 make_sound() 方法,并向控制台输出不同的声音。
我们创建了两个对象,一个是 Dog 类的实例,一个是 Cat 类的实例,并对它们调用 make_sound() 方法。由于每个对象都继承了 Animal 类的 make_sound() 方法,但是子类中的实现不同,因此它们通过多态性体现出不同的行为。
super() 函数
在 Python 中,super() 函数用于在派生类中调用基类的方法。这对于子类重写基类方法时非常有用,因为你仍然可以接受基类的行为。
我们来看一个示例程序,我们定义了一个名为 Person 的基类,并在该类中定义了一个 greet() 方法。然后我们创建一个名为 Student 的派生类,并在其中重写了 greet() 方法。在新的 greet() 方法中,我们调用了基类的实现,以确保仍然打印基本的问候语。
class Person:
def greet(self):
print('Hello, world!')
class Student(Person):
def greet(self):
super().greet()
print('My name is %s.' % self.name)
s = Student()
s.name = 'Tom'
s.greet() # Output: Hello, world! My name is Tom.
在上面的代码中,我们首先定义了一个 Person 类,并在该类中定义了一个 greet() 方法。然后,我们定义了一个 Student 类,并在其中重写了 greet() 方法。我们在新的 greet() 方法中使用 super() 函数来调用基类的实现,并在之后添加了我们自己的行为。
我们创建了一个 Student 实例,并将其 name 属性设置为 ‘Tom’。然后,我们调用它的 greet() 方法,由于它是从父类继承过来的,因此打印了’Hello, world!’。然后,我们在自己的方法中打印了自己的问候语。
结论
在 Python 中,构造函数 init 是一种特殊的方法,用于在对象创建时自动执行初始化代码。我们可以使用它来初始化对象的实例变量,并执行其他必要的初始化工作。
当我们使用类来创建新的对象时,Python 会自动调用 init 函数,并将该对象作为第一个参数传递给它。我们可以在 init 函数中对该对象进行初始化,并确保它具有适当的初始状态。
在 Python 中,有两种类型的变量:实例变量和类变量。实例变量是对象的属性,每个对象都有自己的副本。类变量是共享的,它们属于类而不是任何特定的实例。
我们还学习了在构造函数中如何接受参数,如何使用继承和多态性,并如何使用 super() 函数来调用基类的方法。掌握这些概念可以使我们更好地理解 Python 中的构造函数 init,并使我们能够更有效地创建和使用类。