第9章. 类

  • 9.1 创建和使用类
  • 9.1.1 创建 Dog 类
  • 9.1.2 根据类创建实例
  • 9.2 使用类和实例
  • 9.2.1 Car 类
  • 9.2.2 给属性指定默认值
  • 9.2.3 修改属性的值
  • 9.3 继承
  • 9.3.1 子类的方法__init__()
  • 9.3.2 给子类定义属性和方法
  • 9.3.3 重写父类的方法
  • 9.3.4 将实例用作属性
  • 9.3.5 模拟实物
  • 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.5 Python 标准库
  • 9.6 类编码风格

 

  • 9.1.1 创建 Dog 类

  根据类来创建对象称为实例化

  根据约定,在 Python 中,首字母大写的名称指的是类

示例(以下代码这节还不能完全理解):

 1 class Dog:
 2     """一次模拟小狗的简单尝试"""
 3     def __init__(self,name,age):
 4         """初始化属性 name 和 age"""
 5         self.name = name
 6         self.age = age
 7         
 8     def sit(self):
 9         """模拟小狗收到命令时蹲下"""
10         print(f"{self.name} is now sitting.")
11         
12     def roll_over(self):
13         """模拟小狗收到命令时打滚"""
14         print(f"{self.name} rolled over!")

  类中的函数称为方法。 __init()__ 是一个特殊方法,每当你根据 Dog 类创建新实例时,Python 都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定。

  我们将方法 __init()__ 定义成包含三个形参:self、name和age。在这个方法的定义中,形参 self 必不可少而且必须位于其他形参的前面。为何必须在方法定义中包含形参 self 呢?因为 Python 调用这个方法来创建 Dog实例时,将自动传入实参 self。每个与实例相关联的方法调用都自动传递实参 self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。我们通过实参向 Dog() 传递名字和年龄,self 会自动传递,因此不需要传递它。每当根据 Dog 类创建实例时,都只需给最后两个形参(name 和 age)提供值

  self.name 和 self.age 两个变量都有前缀 self。以 self 为前缀的变量可供类中的所有方法使用,可以通过类的任何实例来访问。

  Dog 类还定义了另外两个方法:sit() 和 roll_over()。这些方法执行时不需要额外的信息,因此它们只有一个形参 self

 

  • 9.1.2 根据类创建实例

  可将类视为有关如何创建实例的说明。

下面创建一个特定小狗的实例:

 1 class Dog:
 2     --snip--
 3 
 4 my_dog = Dog('Willie',6)
 5 
 6 print(f"My dog's name is {my_dog.name}.")
 7 print(f"My dog is {my_dog.age} years old.")
 8 
 9 my_dog.sit()
10 my_dog.roll_over()

res:

  

  访问属性调用方法 都可使用句点表示法

  命名约定很有用:通常可认为首字母大写的名称(如 Dog)指的是类,而小写的名称(如 my_dog)指的是根据类创建的实例

 

  • 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())

res:

  

之前没注意到的:当一个字符串中有空格时,再对此字符串使用 title(),那么此字符串的第一个和每个空格后的第一个字符都将大写,其他位置的字符小写

1 s1 = "qwe eRT yui"
2 print(s1.title())

res:

  

 

  • 9.2.2 给属性指定默认值

  创建实例时,有些属性无须通过形参来定义,可在方法 __init()__ 中为其指定默认值。

 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         self.odometer_reading = 0
10 
11     def get_descriptive_name(self):
12         """返回整洁的描述性信息"""
13         long_name = f"{self.year} {self.make} {self.model}"
14         return  long_name.title()
15 
16     def read_odometer(self):
17         """打印一条指出汽车里程的消息"""
18         print(f"This car has {self.odometer_reading} miles on it.")
19 
20 my_new_car = Car('audi','a4',2019)
21 print(my_new_car.get_descriptive_name())
22 my_new_car.read_odometer()

res:

  

 

  • 9.2.3 修改属性的值

  三种方式:直接通过实例进行修改,通过方法进行设置,通过方法进行递增(和前一种差不多

  • 1. 直接修改属性的值
1 class Car:
2     --snip--
3 
4 my_new_car = Car('audi','a4',2019)
5 print(my_new_car.get_descriptive_name())
6 
7 my_new_car.odometer_reading = 23
8 my_new_car.read_odometer()

res:

  

  • 2. 通过方法修改属性的值
 1 class Car:
 2     --snip--
 3 
 4     def update_odometer(self,mileage):
 5         """将里程表读书设置为指定的值"""
 6         self.odometer_reading = mileage
 7 
 8 my_new_car = Car('audi','a4',2019)
 9 print(my_new_car.get_descriptive_name())
10 
11 my_new_car.update_odometer(23)
12 my_new_car.read_odometer()

res:

  

  • 3. 通过方法对属性的值进行递增
 1 class Car:
 2     --snip--
 3 
 4     def update_odometer(self, mileage):
 5         --snip--
 6 
 7     def increment_odometer(self,miles):
 8         """将里程表读数增加指定的量"""
 9         self.odometer_reading += miles
10 
11 my_new_car = Car('audi','a4',2019)
12 print(my_new_car.get_descriptive_name())
13 
14 my_new_car.update_odometer(23_500)
15 my_new_car.read_odometer()
16 
17 my_new_car.increment_odometer(100)
18 my_new_car.read_odometer()

res:

  

 

  • 9.3 继承

  一个类继承另一个类时,将自动获得另一个类的所有属性和方法

 

  • 9.3.1 子类的方法 __init()__

  在既有类的基础上编写新类时,通常要调用父类的方法 __init()__。这将初始化在父类 __init()__ 方法中定义的所有属性,从而让子类包含这些属性

 1 class Car:
 2     --snip--
 3 
 4 class ElectricCar(Car):
 5     """电动汽车的独特之处"""
 6 
 7     def __init__(self,make,model,year):
 8         """初始化父类的属性"""
 9         super().__init__(make,model,year)
10 
11 my_tesla = ElectricCar('tesla','model s',2019)
12 print(my_tesla.get_descriptive_name())

res:

  

  创建子类时,父类必须包含在当前文件中,且位于子类前面。

  定义子类时,必须在圆括号内指定父类的名称。方法 __init()__ 接受创建 Car 实例所需的信息。

  第 9 行的 super() 是一个特殊函数,让你能够调用父类的方法。这行代码让 Python 调用 Car 类的方法 __init()__ ,让 ElectricCar 实例包含这个方法中定义的所有属性。父类也称为超类( superclass ),名称 super 由此而来。

 

  • 9.3.2 给子类定义属性和方法
 1 class Car:
 2     --snip--
 3 
 4 class ElectricCar(Car):
 5     """电动汽车的独特之处"""
 6 
 7     def __init__(self,make,model,year):
 8         """初始化父类的属性"""
 9         super().__init__(make,model,year)
10         self.battery_size = 75
11 
12     def describe_battery(self):
13         """打印一条描述电瓶容量的消息"""
14         print(f"This car has a {self.battery_size}-kWh battery.")
15 
16 my_tesla = ElectricCar('tesla','model s',2019)
17 print(my_tesla.get_descriptive_name())
18 my_tesla.describe_battery()

res:

  

  根据 EletricCar 类创建的所有实例都将包含属性 battery_size,但所有 Car 实例都不包含它。

 

  • 9.3.3 重写父类的方法

  可在子类中定义一个要重写的父类方法同名的方法。这样,Python 将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

  假设 Car 类有一个名为 fill_gas_tank() 的方法,它对全电动汽车来说毫无意义,因此你可能想重写它。下面演示了一种重写方式:

1 class ElectricCar(Car):
2     --snip--
3 
4         def fill_gas_tank(self):
5             """电动汽车没有油箱"""
6             print("This car doesn't need a gas tank!")

 

  • 9.3.4 将实例用作属性
 1 class Car:
 2     --snip--
 3 
 4 class Battery:
 5     """一次模拟电动汽车电瓶的简单尝试"""
 6 
 7     def __init__(self,battery_size=75):
 8         """初始化电瓶的属性"""
 9         self.battery_size = battery_size
10 
11     def describe_battery(self):
12         """打印一条描述电瓶容量的消息"""
13         print(f"This car has a {self.battery_size}-kWh battery.")
14 
15 class ElectricCar(Car):
16     """电动汽车的独特之处"""
17 
18     def __init__(self,make,model,year):
19         """初始化父类的属性"""
20         super().__init__(make,model,year)
21         self.battery = Battery()
22 
23 my_tesla = ElectricCar('tesla','model s',2019)
24 print(my_tesla.get_descriptive_name())
25 my_tesla.battery.describe_battery()

res:

  

  第 4 行定义了一个新类 Battery,它没有继承任何类。第 7 行的方法 __init()__ 除 self 外,还有另一个形参 battery_size。这个形参是可选的:如果没有给它提供值,电瓶容量将被设置为75。

  在 ElectricCar 类中,添加了一个名为 self.battery 的属性。第 21 行代码让 Python 创建一个新的 Battery 实例(因为没有指定容量,所以为默认值 75),并将该实例赋给属性 self.battery。

 

  • 9.4.1 导入单个类

让 Python 打开模块 car.py 并导入其中的 Car 类。

from car import Car

然后直接用导入的类

 

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

  从一个模块中导入多个类时,用逗号分隔了各个类

从 car.py 导入类 Car 和 ElectricCar

from car import Car, ElectricCar

然后直接用导入的类

 

  • 9.4.4 导入整个模块

  可以导入整个模块,再使用句点表示法访问需要的类

导入整个模块 car

import car

访问语法

module_name.ClassName

 

  • 9.4.5 导入模块中的所有类
from module_name import *

访问语法

module_name.ClassName

 

  • 9.4.7 使用别名
from electric_car import ElectricCar as EC

给 ElectricCar 指定别名 EC

 

  • 9.5 Python 标准库

  Python 标准库是一组模块,我们安装的 Python 都包含它。

  下面来看看模块 random

  在这个模块中,一个有趣的函数是 randint()。它将两个整数作为参数,并随机返回一个位于这两个整数之间(含)的整数

  另一个有用的函数是 choice()。它将一个列表或元组作为参数,并随机返回其中一个元素

1 from random import randint
2 from random import choice
3 
4 print(randint(1,6))
5 
6 players = ['charles','martina','michael','forence','ali']
7 print(choice(players))

res:

  

 

  • 9.6 类编码风格

  类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线

(〃>_<;〃)(〃>_<;〃)(〃>_<;〃)

posted @ 2023-06-07 20:38  我会变强的  阅读(11)  评论(0编辑  收藏  举报