创建和使用类
您几乎可以使用类对任何事物进行建模。 让我们从编写一个简单的类 Dog 开始,它代表一只狗——不是特定的一只狗,而是任何一只狗。 我们对大多数宠物狗了解多少? 嗯,他们都有名字和年龄。 我们也知道大多数狗会坐着翻身。 这两条信息(姓名和年龄)和这两种行为(坐下和翻身)将进入我们的 Dog 类,因为它们对大多数狗来说都很常见。 这个类将告诉 Python 如何制作一个代表狗的对象。 编写完我们的类后,我们用它来创建单独的实例,每个实例都代表一只特定的狗。
创建Dog类
从 Dog 类创建的每个实例都将存储一个名字和一个年龄,我们将赋予每只狗 sit() 和 roll_over() 的能力:
class Dog: (1)
"""A simple attempt to model a dog."""
def __init__(self, name, age): (2)
"""Initialize name and age attributes."""
self.name = name (3)
self.age = age
def sit(self): (4)
"""Simulate a dog sitting in response to a command."""
print(f"{self.name} is now sitting.")
def roll_over(self):
"""Simulate rolling over in response to a command."""
print(f"{self.name} rolled over!")
这里有很多需要注意的地方,但不要担心。 您将在本章中看到这种结构,并且有很多时间来习惯它。 我们首先定义一个类,叫做 Dog。 按照惯例,大写的名称指的是 Python 中的类。 类定义中没有括号,因为我们是从头开始创建这个类。 然后我们写一个文档字符串来描述这个类做了什么。
init() 方法
作为类一部分的函数是方法。 您学到的有关函数的所有内容也适用于方法; 现在唯一实际的区别是我们调用方法的方式。 __init__()
方法是一个特殊的方法,每当我们基于 Dog 类创建一个新实例时,Python 就会自动运行该方法。 此方法有两个前导下划线和两个尾随下划线,这是一种有助于防止 Python 的默认方法名称与您的方法名称冲突的约定。 确保在 __init__()
的每一侧使用两个下划线。 如果你只在每一侧使用一个,当你使用你的类时,该方法将不会被自动调用,这可能会导致难以识别的错误。
我们将 __init__()
方法定义为具有三个参数:self
、name
和 age
。 方法定义中需要 self
参数,它必须在其他参数之前。 它必须包含在定义中,因为当 Python 稍后调用此方法(创建 Dog 的实例)时,方法调用将自动传递 self 参数。 每个与实例关联的方法调用都会自动传递 self,这是对实例本身的引用; 它使单个实例可以访问类中的属性和方法。 当我们创建 Dog 的实例时,Python 将调用 Dog 类的 __init__()
方法。 我们将向 Dog() 传递一个名字和一个年龄作为参数; self 是自动传递的,所以我们不需要传递它。 每当我们想要从 Dog 类创建一个实例时,我们将只提供最后两个参数的值,name 和 age。
__init__()
方法体中定义的两个变量都带有前缀 self
。 类中的每个方法都可以使用任何以 self
为前缀的变量,我们也可以通过从类创建的任何实例访问这些变量。 self.name = name 行获取与参数名称关联的值并将其分配给变量名称,然后将其附加到正在创建的实例。 同样的过程发生在 self.age = age 上。 可通过此类实例访问的变量称为属性。
Dog 类定义了另外两个方法:sit()
和 roll_over()
。 因为这些方法不需要额外的信息来运行,我们只是将它们定义为具有一个参数,self。 我们稍后创建的实例将可以访问这些方法。 换句话说,他们将能够坐下并翻身。 目前,sit() 和 roll_over() 做的不多。 他们只是打印一条消息,说狗正坐着或翻身。 但这个概念可以扩展到现实情况:如果这个类是电脑游戏的一部分,这些方法将包含让一只动画狗坐下并翻身的代码。 如果编写此类是为了控制机器人,则这些方法将引导导致机器狗坐下和翻身的动作。
根据类创建实例
将类视为一组关于如何创建实例的指令。 Dog 类是一组指令,告诉 Python 如何使单个实例代表特定的狗。
让我们创建一个代表具体狗的实例:
my_dog = Dog('Willie', 6) (1)
print(f"My dog's name is {my_dog.name}.") (2)
print(f"My dog is {my_dog.age} years old.") (3)
1 | 我们在这里使用的 Dog 类是我们刚刚在上一个示例中编写的类。 在这里,我们告诉 Python 创建一只狗,它的名字是“Willie”,年龄是 6。 当 Python 读取这一行时,它会使用参数“Willie”和 6 调用 Dog 中的 __init__() 方法。__init__() 方法创建一个代表这只特定狗的实例,并使用我们提供的值设置 name 和 age 属性。 Python 然后返回代表这只狗的实例。 我们将该实例分配给变量 my_dog。 命名约定在这里很有帮助; 我们通常可以假设像 Dog 这样的大写名称是指类,而像 my_dog 这样的小写名称是指从类创建的单个实例。 |
访问属性
要访问实例的属性,您可以使用点表示法。 我们访问 my_dog 的属性名的值是这样写的:
my_dog.name
点符号在 Python 中经常使用。 此语法演示了 Python 如何查找属性的值。 在这里,Python 查看实例 my_dog,然后找到与 my_dog 关联的属性名称。 这与 Dog 类中称为 self.name 的属性相同。 我们使用相同的方法来处理属性 age 。
输出是我们对 my_dog 的了解的总结:
My dog's name is Willie.
My dog is 6 years old.
调用方法
从类 Dog 创建实例后,我们可以使用点表示法调用 Dog 中定义的任何方法。 让我们的狗坐下并翻身:
class Dog:
"""A simple attempt to model a dog."""
def __init__(self, name, age):
"""Initialize name and age attributes."""
self.name = name
self.age = age
def sit(self):
"""Simulate a dog sitting in response to a command."""
print(f"{self.name} is now sitting.")
def roll_over(self):
"""Simulate rolling over in response to a command."""
print(f"{self.name} rolled over!")
my_dog = Dog('Willie', 6)
my_dog.sit()
my_dog.roll_over()
要调用方法,请提供实例名称(在本例中为 my_dog)和您要调用的方法,以点分隔。 当 Python 读取 my_dog.sit() 时,它会在类 Dog 中查找方法 sit() 并运行该代码。 Python 以相同的方式解释 my_dog.roll_over() 行。
现在威利按照我们告诉他的去做:
Willie is now sitting.
Willie rolled over!
这个语法非常有用。 当属性和方法被赋予适当的描述性名称,如 name、age、sit() 和 roll_over() 时,我们可以很容易地推断出一段代码(即使是我们以前从未见过的)应该做什么。
创建多个实例
您可以根据需要从一个类中创建任意数量的实例。 让我们创建第二只狗,叫做 your_dog:
class Dog:
"""A simple attempt to model a dog."""
def __init__(self, name, age):
"""Initialize name and age attributes."""
self.name = name
self.age = age
def sit(self):
"""Simulate a dog sitting in response to a command."""
print(f"{self.name} is now sitting.")
def roll_over(self):
"""Simulate rolling over in response to a command."""
print(f"{self.name} rolled over!")
my_dog = Dog('Willie', 6)
your_dog = Dog('Lucy', 3)
print(f"My dog's name is {my_dog.name}.")
print(f"My dog is {my_dog.age} years old.")
my_dog.sit()
print(f"\nYour dog's name is {your_dog.name}.")
print(f"Your dog is {your_dog.age} years old.")
your_dog.sit()
在本例中,我们创建了一只名为 Willie 的狗和一只名为 Lucy 的狗。 每只狗都是一个单独的实例,具有自己的一组属性,能够执行相同的一组操作:
My dog's name is Willie.
My dog is 6 years old.
Willie is now sitting.
Your dog's name is Lucy.
Your dog is 3 years old.
Lucy is now sitting.
即使我们为第二只狗使用相同的名字和年龄,Python 仍会从 Dog 类创建一个单独的实例。 您可以根据需要从一个类中创建尽可能多的实例,只要您为每个实例指定一个唯一的变量名称,或者它在列表或字典中占据一个唯一的位置。