Python:从入门到实践-第九章(笔记)
9.1 : 创建和使用类
使用类几乎可以模拟任何东西
9.1.1 : 创建Dog类
每当根据Dog类创建一个实例时,该实例将被记录其叫名及年龄信息,并被赋予蹲下和打滚的能力.
# 定义一个名为Dog的类
class Dog:
"""一次模拟小狗的简单尝试"""
# 类中的函数称为方法:方法__init__();
# 方法__init__()定义成包含三个形参:self、name、和age;
# 形参self必不可少,必须位于其他形参的前面;
# 通过实参向Dog()传递名字和年龄,self会自动传递
def __init__(self, name, age):
"""初始化属性name和age"""
# 获取与行参name和age相关的取值,并将其赋给变量name和age,然后该变量关联到当前创建的实例;
self.name = name
self.age = age
def sit(self):
"""模拟小狗收到命令时蹲下"""
print(f"{self.name} is now sitting.")
def roll_over(self):
"""模拟小狗收到命令时打滚"""
print(f"{self.name} rolled over!")
9.1.2 :根据类创建实例
其可被视为关于创建实例的定义。Dog类是一系列定义告诉Python生成表示特定小狗的对象。
# 定义一个名为Dog的类
class Dog:
"""一次模拟小狗的简单尝试"""
# 类中的函数称为方法:方法__init__();
# 方法__init__()定义成包含三个形参:self、name、和age;
# 形参self必不可少,必须位于其他形参的前面;
# 通过实参向Dog()传递名字和年龄,self会自动传递
def __init__(self, name, age):
"""初始化属性name和age"""
# 获取与行参name和age相关的取值,并将其赋给变量name和age,然后该变量关联到当前创建的实例;
self.name = name
self.age = age
def sit(self):
"""模拟小狗收到命令时蹲下"""
print(f"{self.name} is now sitting.")
def roll_over(self):
"""模拟小狗收到命令时打滚"""
print(f"{self.name} rolled over!")
# 让python创建一条名字为'Willie'、年龄为6的小狗。
my_dog = Dog('Willie', 6)
your_dog = Dog('Lucy', 3)
my_dog.sit()
my_dog.roll_over()
# 编写了如下代码来访问my_dog的属性name和age的值;
print(f"\nMy 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()
运行结果:
现在威利正在坐着。
威利翻了个身。
我家宠物的名字叫威利。
我的宠物已经陪伴我六岁了。
现在威利正在坐着。
我的朋友家有一条宠物的名字叫露西。
我的伴侣已经陪伴我三年了。
露西现在 lying down.
9.2:使用类和实例
该技术可用于模仿现实世界中的多种场景。一个类不仅具有能力去复制实例的各种属性,并且能够通过定义一系列操作来实现特定的更改。
9.2.1:Car 类
创建一个能够存储与汽车相关的信息,并且包含汇总这些信息的方法。
class Car:
"""一次模拟汽车的简单尝试"""
# 定义方法,该方法还包含另外三个形参:make、model和year
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
# 定义一个名为get_descriptive_name的方法,它使用属于year、make和model创建一个对汽车进行描述的字符串;
def get_descriptive_name(self):
"""返回整洁的描述性信息"""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
# 根据Car类创建一个实例,并将其赋给变量my_new_car;
my_new_car = Car('audi', 'a4', 2019)
print(my_new_car.get_descriptive_name())
9.2.2 :给属性指定默认值
当创建实例时,在构造函数中为这些属性设置默认值,并不需要在参数列表中显式声明它们。
class Car:
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
# 添加一个名为odmeter_reading的属性,其初始值总是为0
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述性信息"""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
# 定义一个名为read_odometer的方法
def read_odometer(self):
"""打印一条指出汽车里程的消息"""
print(f"This car has {self.odometer_reading} miles on it.")
my_new_car = Car('audi', 'a4', '2019')
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
9.2.3 :修改属性的值
以三种方式修改属性的值:
- 基于实例的调整
- 采用方式设置参数
- 并利用递增操作设定指定增量值
a. 直接修改属性的值
class Car:
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
# 添加一个名为odometer_reading的属性,其初始值总是为0
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述性信息"""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
# 定义一个名为read_odometer的方法
def read_odometer(self):
"""打印一条指出汽车里程的消息"""
print(f"This car has {self.odometer_reading} miles on it.")
my_new_car = Car('audi', 'a4', '2019')
print(my_new_car.get_descriptive_name())
# 使用句点表示法直接访问并设置汽车的属性odometer_reading.
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
b. 通过方法修改属性的值
class Car:
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述性信息"""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
"""打印一条指出汽车里程的消息"""
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
"""
将里程表读数设置为指定的值
禁止将里程表读数往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
my_new_car = Car('audi', 'a4', 2019)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(23)
my_new_car.read_odometer()
c. 通过方法对属性的值进行递增
class Car:
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""返回整洁的描述性信息"""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
"""打印一条指出汽车里程的消息"""
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
"""
将里程表读数设置为指定的值
禁止将里程表读数往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
# 新增方法,接受一个单位为英里的数,并将其加入self.odometer_reading中;
def increment_odometer(self, miles):
"""将里程表读数增加指定的量"""
self.odometer_reading += miles
my_used_car = Car('subaru', 'outback', 2015)
print(my_used_car.get_descriptive_name())
my_used_car.update_odometer(23_500)
my_used_car.read_odometer()
my_used_car.increment_odometer(100)
my_used_car.read_odometer()
9.3:继承
编写一个新代码块时,并非总是要从头开始。当一个新定义的代码块继承已存在的代码块时(即其语法结构或数据类型与其原有代码块相同),该系统会自动获取原有代码块的所有属性与方法(即其成员变量与函数)。原有被继承的那个则被称为父类别(parent class),而新定义的那个则被称为子类别(subclass)。原有的那个称为父类别(parent class);而新定义的那个则被称为子类别(subclass)。
9.3.1 : 子类的方法__init__()
在既有类的基础上编写新类时,通常要调用父类的方法 init().
例子:
# 创建子类时候,父类必须在子类前;
class Car:
"""一次模拟汽车的简单尝试"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer! ")
def increment_odometer(self, miles):
self.odometer_reading += miles
# 定义了子类ElectricCar,定义子类时,必须在圆括号内指定父类的名称;
class ElectricCar(Car):
"""电动汽车的独特之处"""
# 方法 init 接受创建Car实例所需的信息
def __init__(self, make, model, year):
"""初始化父类的属性"""
# super()是一个特殊函数,让你能够调用父类的方法。
super().__init__(make, model, year)
# 创建ElectricCar类的一个实例,并将其赋给变量my_tesla.
my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
9.3.2 给子类定义属性和方法
通过类继承机制,在子类与父类之间可以增添所需的新属性和新方法。
# 创建子类时候,父类必须在子类前;
class Car:
"""一次模拟汽车的简单尝试"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer! ")
def increment_odometer(self, miles):
self.odometer_reading += miles
# 定义了子类ElectricCar,定义子类时,必须在圆括号内指定父类的名称;
class ElectricCar(Car):
"""电动汽车的独特之处"""
# 方法 init 接受创建Car实例所需的信息
def __init__(self, make, model, year):
"""
初始化父类的属性
再初始化电动汽车特有的属性
"""
# super()是一个特殊函数,让你能够调用父类的方法。
super().__init__(make, model, year)
# 添加新属性self.battery_size, 并设置其初始值75
self.battery_size = 75
# 添加了一个名为describe_battery()的方法,打印有关电瓶的信息;
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print(f"This car has a {self.battery_size}-KWh battery. ")
# 创建ElectricCar类的一个实例,并将其赋给变量my_tesla.
my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
9.3.3 : 重写父类的方法
对于父类的方法,只要它不符合子类模拟的实物的行为,都可以进行重写。
# 创建子类时候,父类必须在子类前;
class Car:
"""一次模拟汽车的简单尝试"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer! ")
def increment_odometer(self, miles):
self.odometer_reading += miles
# 定义了子类ElectricCar,定义子类时,必须在圆括号内指定父类的名称;
class ElectricCar(Car):
"""电动汽车的独特之处"""
# 方法 init 接受创建Car实例所需的信息
def __init__(self, make, model, year):
"""
初始化父类的属性
再初始化电动汽车特有的属性
"""
# super()是一个特殊函数,让你能够调用父类的方法。
super().__init__(make, model, year)
# 添加新属性self.battery_size, 并设置其初始值75
self.battery_size = 75
# 添加了一个名为describe_battery()的方法,打印有关电瓶的信息;
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print(f"This car has a {self.battery_size}-KWh battery. ")
def fill_gas_tank(self):
"""电动汽车没有油箱"""
print("This car doesn't need a gas tank!")
# 创建ElectricCar类的一个实例,并将其赋给变量my_tesla.
my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
my_tesla.fill_gas_tank()
9.3.4 :将实例用作属性
首先从一个现有的类中分离出一部分代码,并将其单独成为一个新的子类;然后对于大型类来说,我们将其分解为若干个相互协作的小模块。
# 创建子类时候,父类必须在子类前;
class Car:
"""一次模拟汽车的简单尝试"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer! ")
def increment_odometer(self, miles):
self.odometer_reading += miles
class Battery:
"""一次模拟电动汽车电瓶的简单尝试"""
def __init__(self, battery_size=75):
"""初始化电瓶的属性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print(f"This car has a {self.battery_size}-KWh battery.")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""
初始化父类属性
再初始化电动汽车特有的属性
"""
super().__init__(make, model, year)
self.battery = Battery()
my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
给Battery类添加一个方法,它根据电瓶容量报告汽车的续航里程:
# 创建子类时候,父类必须在子类前;
class Car:
"""一次模拟汽车的简单尝试"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer! ")
def increment_odometer(self, miles):
self.odometer_reading += miles
class Battery:
"""一次模拟电动汽车电瓶的简单尝试"""
def __init__(self, battery_size=75):
"""初始化电瓶的属性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print(f"This car has a {self.battery_size}-KWh battery.")
def get_range(self):
"""打印一条消息,指出电瓶的续航里程"""
if self.battery_size == 75:
range = 260
elif self.battery_size == 100:
range = 315
print(f"This car can go about {range} miles on a full charge.")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""
初始化父类属性
再初始化电动汽车特有的属性
"""
super().__init__(make, model, year)
self.battery = Battery()
my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
9.4 :导入类
每当为类添加功能时(even when adding functionalities to a class),文件可能会变得非常长),即便合理地利用了继承机制(even with proper use of inheritance)也是如此(it still may become lengthy)。因此(therefore),为了使文件尽可能简洁明了(to keep the file as concise and clear as possible),建议将类存储在模块中(store the class in a module),然后在主程序中导入所需模块(and then import the required modules in the main program)。
9.4.1:导入单个类
# 让Python 打开模块car并导入其中的Car类
from car import Car
my_new_car = Car('audi', 'a4', 2019)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
9.4.2 : 在一个模块中存储多个类
# 创建子类时候,父类必须在子类前;
class Car:
"""一次模拟汽车的简单尝试"""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer! ")
def increment_odometer(self, miles):
self.odometer_reading += miles
class Battery:
"""一次模拟电动汽车电瓶的简单尝试"""
def __init__(self, battery_size=75):
"""初始化电瓶的属性"""
self.battery_size = battery_size
def describe_battery(self):
"""打印一条描述电瓶容量的消息"""
print(f"This car has a {self.battery_size}-KWh battery.")
def get_range(self):
"""打印一条消息,指出电瓶的续航里程"""
if self.battery_size == 75:
range = 260
elif self.battery_size == 100:
range = 315
print(f"This car can go about {range} miles on a full charge.")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""
初始化父类属性
再初始化电动汽车特有的属性
"""
super().__init__(make, model, year)
self.battery = Battery()
导入ElectricCar类
from car import ElectricCar
my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
9.4.3 : 从一个模块中导入多个类
from car import Car, ElectricCar
my_beetle = Car('volkswagen', 'beetle', 2019)
print(my_beetle.get_descriptive_name())
my_beetle = ElectricCar('tesla', 'roadster', 2019)
print(my_beetle.get_descriptive_name())
9.4.5 : 导入整个模块
import car
my_beetle = car.Car('volkswagen', 'beetle', 2019)
print(my_beetle.get_descriptive_name())
my_beetle = car.ElectricCar('tesla', 'roadster', 2019)
print(my_beetle.get_descriptive_name())
9.4.5 :导入模块中的所有类
from module_name import *
不推荐使用这种导入方式:
- 没有明确地指出使用了模块中的哪些类
- 引发名称方面的迷惑
9.46 :在一个模块中导入另一个模块
from car import Car
from electric_car import ElectricCar
my_beetle = Car('volkswagen', 'beetle', 2019)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar('tesla', 'roadster', 2019)
print(my_tesla.get_descriptive_name())
9.4.7 : 使用别名
导入类时,也可为指定别名:
比如:
from electric_car import ElectricCar as EC
my_tesla = EC('tesla', 'roadster', 2019)
9.5 : Python标准库
Python标准库是一组模块,我们安装的Python都包含它。
该函数 randont() 接受两个整数作为输入参数,并在其间生成一个随机的整数值。
例如:生成一个位于1和6之间的随机整数:
from random import randint
print(randint(1, 6))
在模块random中,另一个有实用价值的函数是choice()。该函数接受一个列表或元组作为输入,并从其中随机选取一个元素进行返回。
from random import choice
players = ['charles', 'martina', 'michael', 'florence', 'eli']
first_up = choice(players)
print(first_up)
