当前位置:   article > 正文

《Python编程:从入门到实践》第 9 章 类_练习9.4 类

练习9.4 类

目录

9.1 创建和使用类

9.1.1 创建Dog 类

方法__init__()

9.1.2 根据类创建实例

a. 访问属性

b. 调用方法

c. 创建多个实例

9.1.3 练习

练习9-1:餐馆

练习9-2:三家餐馆

练习9-3:用户

9.2 使用类和实例

9.2.1 Car 类

9.2.2 给属性指定默认值

9.2.3 修改属性的值

a. 直接修改属性的值

b. 通过方法修改属性的值

c. 通过方法对属性的值进行递增

9.2.4 练习 

练习9-4:就餐人数

练习9-5:尝试登录次数

9.3 继承

9.3.1 子类的方法__init__()

9.3.2 给子类定义属性和方法

9.3.3 重写父类的方法

9.3.4 将实例用作属性

9.3.5 模拟实物

9.3.6 练习

练习9-6:冰激凌小店

练习9-7:管理员

练习9-8:权限

练习9-9:电瓶升级

9.4 导入类

9.4.1 导入单个类

9.4.2 在一个模块中存储多个类

9.4.3 从一个模块中导入多个类

9.4.4 导入整个模块

9.4.5 导入模块中的所有类

9.4.6 在一个模块中导入另一个模块

9.4.7 使用别名

9.4.8 自定义工作流程

9.4.9 练习

练习9-10:导入Restaurant 类

练习9-11:导入Admin 类

练习9-12:多个模块

9.5 Python标准库

9.5.1 练习 

练习9-13:骰子

练习9-14:彩票

练习9-15:彩票分析

练习9-16:Python Module of the Week

 9.6 类编码风格


 

9.1 创建和使用类

使用类几乎可以模拟任何东西。下面来编写一个表示小狗的简单类Dog ,它表示的不是特定的小狗,而是任何小狗。对于大多数宠物狗,我们都知道些什么呢?它们都有名字和年龄。我们还知道,大多数小狗还会蹲下和打滚。由于大多数小狗都具备上述两项信息(名字和年龄)和两种行为(蹲下和打滚),我们的Dog 类将包含它们。这个类让Python知道如何创建表示小狗的对象。编写这个类后,我们将使用它来创建表示特定小狗的实例。

9.1.1 创建Dog

根据 Dog 类创建的每个实例都将存储名字和年龄,我们赋予了每条小狗蹲下( sit() )和打滚( roll_over() )的能力:
  1. class Dog:
  2. """一次模拟小狗的简单尝试。"""
  3. def __init__(self, name, age):
  4. """初始化属性name和age。"""
  5. #❹
  6. self.name = name
  7. self.age = age
  8. def sit(self):
  9. """模拟小狗收到命令时蹲下。"""
  10. print(f"{self.name} is now sitting.")
  11. def roll_over(self):
  12. """模拟小狗收到命令时打滚。"""
  13. print(f"{self.name} rolled over!")
这里需要注意的地方很多,但也不用担心,本章充斥着这样的结构,你有大把的机会熟悉它。 定义了一个名为 Dog 的类。根据约定,在Python中,首字母大写的名称指的是类。这个类定义中没有圆括号,因为要从空白创建这个类。编写了一个文档字符串,对这个类的功能做了描述。

方法__init__()

类中的函数称为 方法 。你在前面学到的有关函数的一切都适用于方法,就目前而言,唯一重要的差别是调用方法的方式。 方法 __init__() 是一个特殊方法,每当你根据Dog 类创建新实例时,Python都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。务必确保 __init__() 的两边都有两个下划线,否则当你使用类来创建实例时,将不会自动调用这个方法,进而引发难以发现的错误。 我们将方法 __init__() 定义成包含三个形参: self name age 。 在这个方法的定义中 形参self 必不可少, 而且 必须位于其他形参的前面
为何必须在方法定义中包含形参 self 呢?因为Python调用这个方法来创建 Dog 实例时,将自动传入实参 self 。每个与实例相关联的方法调用都自动传递实参 self ,它是 一个指向实例本身的引用 ,让实例能够访问类中的属性和方法。创建 Dog 实例时,Python将调用 Dog 类的方法 __init__() 。我们将通过实参向 Dog() 传递名字和年龄,self 会自动传递,因此不需要传递它。每当根据 Dog 类创建实例时,都只需给最后两个形参( name age )提供值。
处定义的两个变量都有前缀 self 。以 self 为前缀的变量可供类中的所有方法使用,可以通过类的任何实例来访问。 self.name = name 获取与形参 name 相关联的值,并将其赋给变量 name ,然后该变量被关联到当前创建的实例。self.age= age 的作用与此类似。像这样可通过实例访问的变量称为 属性
Dog 类还定义了另外两个方法: sit() roll_over() 。这些方法执行时不需要额外的信息,因此它们只有一个形参self 。我们随后将创建的实例能够访问这些方法,换句话说,它们都会蹲下和打滚。当前,sit() 和roll_over()所做的有限,只是打印一条消息,指出小狗正在蹲下或打滚。但可以扩展这些方法以模拟实际情况:如果这个类包含在一个计算机游戏中,这些方法将包含创建小狗蹲下和打滚动画效果的代码;如果这个类是用于控制机器狗的,这些方法将让机器狗做出蹲下和打滚的动作。

9.1.2 根据类创建实例

可将类视为有关如何创建实例的说明。 Dog 类是一系列说明,让Python知道如何创建表示特定小狗的实例。
下面来创建一个表示特定小狗的实例:
  1. class Dog:
  2. """一次模拟小狗的简单尝试。"""
  3. def __init__(self, name, age):
  4. """初始化属性name和age。"""
  5. self.name = name
  6. self.age = age
  7. def sit(self):
  8. """模拟小狗收到命令时蹲下。"""
  9. print(f"{self.name} is now sitting.")
  10. def roll_over(self):
  11. """模拟小狗收到命令时打滚。"""
  12. print(f"{self.name} rolled over!")
  13. #❶处
  14. my_dog = Dog('Willie', 6)
  15. #❷处
  16. print(f"My dog's name is {my_dog.name}.")
  17. #❸处
  18. print(f"My dog is {my_dog.age} years old.")
这这里使用的是前一个示例中编写的 Dog 类。在 ❶处,让Python创建一条名字为 'Willie' 、年龄为 6 的小狗。遇到这行代码时,Python使用实参 'Willie' 和6 调用 Dog 类的方法 __init__() 。方法 __init__() 创建一个表示特定小狗的实例,并使用提供的值来设置属性 name age 。接下来,Python返回一个表示这条小狗的实例,而我们将这个实例赋给了 变量my_dog 。在这里,命名约定很有用:通常可认为首字母大写的名称(如 Dog )指的是类,而小写的名称(如my_dog )指的是根据类创建的实例。

a. 访问属性

要访问实例的属性,可使用句点表示法。 处编写了如下代码来访问my_dog的属性 name 的值:
my_dog.name
句点表示法在Python中很常用,这种语法演示了Python如何获悉属性的值。在这里, Python先找到实例 my_dog ,再查找与该实例相关联的属性 name 。在Dog 类中引用这个属性时,使用的是 self.name 。在 ❸处,使用同样的方法来获取属性 age 的值。
输出是有关 my_dog 的摘要:
  1. My dog's name is Willie.
  2. My dog is 6 years old.

b. 调用方法

根据 Dog 类创建实例后,就能使用句点表示法来调用 Dog 类中定义的任何方法了。下面来让小狗蹲下和打滚:
  1. class Dog:
  2. --snip--
  3. my_dog = Dog('Willie', 6)
  4. my_dog.sit()
  5. my_dog.roll_over()
要调用方法,可指定实例的名称(这里是 my_dog )和要调用的方法,并用句点分隔。遇到代码 my_dog.sit() 时,Python在类 Dog 中查找方法 sit() 并运行其代码。Python以同样的方式解读代码 my_dog.roll_over()
Willie按我们的命令做了:
  1. Willie is now sitting.
  2. Willie rolled over!
这种语法很有用。如果给属性和方法指定了合适的描述性名称,如 name 、age、 sit() roll_over() ,即便是从未见过的代码块,我们也能够轻松地推断出它是做什么的。

c. 创建多个实例

可按需求根据类创建任意数量的实例。下面再创建一个名为 your_dog 的小狗实例:
  1. class Dog:
  2. --snip--
  3. my_dog = Dog('Willie', 6)
  4. your_dog = Dog('Lucy', 3)
  5. print(f"My dog's name is {my_dog.name}.")
  6. print(f"My dog is {my_dog.age} years old.")
  7. my_dog.sit()
  8. print(f"\nYour dog's name is {your_dog.name}.")
  9. print(f"Your dog is {your_dog.age} years old.")
  10. your_dog.sit()
在本例中创建了两条小狗,分别名为Willie和Lucy。每条小狗都是一个独立的实例,有自己的一组属性,能够执行相同的操作:
  1. My dog's name is Willie.
  2. My dog is 6 years old.
  3. Willie is now sitting.
  4. Your dog's name is Lucy.
  5. Your dog is 3 years old.
  6. Lucy is now sitting.
即使给第二条小狗指定同样的名字和年龄,Python依然会根据Dog 类创建另一个实例。你可按需求根据一个类创建任意数量的实例,条件是将每个实例都存储在不同的变量中,或者占用列表或字典的不同位置。

9.1.3 练习

练习9-1:餐馆

创建一个名为 Restaurant 的类,为其方法__init__()设置属性 restaurant_name cuisine_type 。创建一个名为describe_restaurant() 的方法和一个名为 open_restaurant() 的方法,前者打印前述两项信息,而后者打印一条消息,指出餐馆正在营业。
根据这个类创建一个名为 restaurant 的实例,分别打印其两个属性,再调用前述两个方法。  
  1. class Restaurant:
  2. """餐馆信息"""
  3. def __init__(self, restaurant_name, cuisine_type):
  4. """初始化属性"""
  5. self.restaurant_name = restaurant_name
  6. self.cuisine_type = cuisine_type
  7. def describe_restaurant(self):
  8. """餐馆信息"""
  9. print(f"This {self.restaurant_name}'s style is {self.cuisine_type}")
  10. def open_restaurant(self):
  11. """营业情况"""
  12. print("opening")
  13. my_restaurant = Restaurant('xiao mi fan dian', 'chuan cai')
  14. my_restaurant.describe_restaurant()
  15. my_restaurant.open_restaurant()

练习9-2:三家餐馆

根据为完成练习9-1而编写的类创建三个实例,并对每个实例调用方法 describe_restaurant()
本题代码和9-1一样添加了如下测试用例:
  1. my_restaurant = Restaurant('xiao mi fan dian', 'chuan cai')
  2. your_restaurant = Restaurant('huazhong fandian', 'xiang cai')
  3. his_restaurant = Restaurant('zhongnan fandian', 'yue cai')
  4. my_restaurant.describe_restaurant()
  5. your_restaurant.describe_restaurant()
  6. his_restaurant.describe_restaurant()

练习9-3:用户

创建一个名为 User 的类,其中包含属性 first_name 和last_name ,以及用户简介通常会存储的其他几个属性。在类 User 中定义一 个名为 describe_user() 的方法,用于打印用户信息摘要。再定义一个名为greet_user() 的方法,用于向用户发出个性化的问候。
创建多个表示不同用户的实例,并对每个实例调用上述两个方法。
  1. class User:
  2. """用户信息"""
  3. def __init__(self, first_name, last_name, **info):
  4. """信息初始化"""
  5. self.first_name = first_name
  6. self.last_name = last_name
  7. self.info = info
  8. def describe_user(self):
  9. """描述用户信息"""
  10. print(f"{self.first_name.title()} {self.last_name.title()}")
  11. print(self.info)
  12. def greet_user(self):
  13. """打招呼"""
  14. print(f"Hello,{self.first_name.title()} {self.last_name.title()}!")
  15. first_person = User('bob', 'cruise', age='14', habit='eat')
  16. first_person.describe_user()
  17. first_person.greet_user()

9.2 使用类和实例

可使用类来模拟现实世界中的很多情景。类编写好后,你的大部分时间将花在根据类创建的实例上。你需要执行的一个重要任务是修改实例的属性。可以直接修改实例的属性,也可以编写方法以特定的方式进行修改。

9.2.1 Car

下面来编写一个表示汽车的类。它存储了有关汽车的信息,还有一个汇总这些信息的方法:
  1. class Car:
  2. """一次模拟汽车的简单尝试。"""
  3. # ❶
  4. def __init__(self, make, model, year):
  5. """初始化描述汽车的属性。"""
  6. self.make = make
  7. self.model = model
  8. self.year = year
  9. # ❷
  10. def get_descriptive_name(self):
  11. """返回整洁的描述性信息。"""
  12. long_name = f"{self.year} {self.make} {self.model}"
  13. return long_name.title()
  14. # ❸
  15. my_new_car = Car('audi', 'a4', 2019)
  16. print(my_new_car.get_descriptive_name())
处,定义了方法 __init__() 。与前面的 Dog 类中一样,这个方法的第一个形参为 self 。该方法还包含另外三个形参: make model year 。方法__init__() 接受这些形参的值,并将它们赋给根据这个类创建的实例的属性。创建新的 Car 实例时,需要指定其制造商、型号和生产年份。
处,定义了一个名为 get_descriptive_name() 的方法。它使用属性year、 make model 创建一个对汽车进行描述的字符串,让我们无须分别打印每个属性的值。为在这个方法中访问属性的值,使用了 self.make self.model 和self.year 。在 处,根据 Car 类创建了一个实例,并将其赋给变量my_new_car 。接下来,调用方法 get_descripti
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/992858
推荐阅读
相关标签
  

闽ICP备14008679号