《Python编程:从入门到实践》学习笔记(5:类)

目录

9 类

9.1 创建和使用类

9.1.1 创建一个简单类

9.1.2 根据类创建实例

9.2 使用类和实例

9.2.1 创建另一个新的类

9.2.2 给属性指定默认值

9.2.3 修改属性的值

9.3 继承

9.3.1 子类的方法__init__()

9.3.2 Python 2.7中的继承

9.3.3 给子类定义属性和方法

9.3.4 重写父类的方法

9.3.5 将实例用作属性

9.3.6 模拟实物

9.4 导入类

9.4.1 导入单个类

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

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

9.4.4 导入整个模块

9.4.5 导入模块中的所有类

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

9.5 Python 标准库


9

面向对象编程是最有效的软件编写方法之一。根据类来创建对象被称为 实例化,这让你能够使用类的实例。

9.1 创建和使用类

9.1.1 创建一个简单类

根据Dog类创建的每个实例都将存储名字和年龄。赋予了每条小狗蹲下(sit())和打滚(roll_over())的能力:

class Dog(): # 定义了一个名为 Dog 的类
    """一次模拟小狗的简单尝试"""
    def __init__(self, name, age):
    #方法 __init__() 定义成了包含三个形参: self 、 name 和 age
        """初始化属性name和age"""
        self.name = name #定义的两个变量都有前缀 self
        self.age = age
    def sit(self):
        """模拟小狗被命令时蹲下"""
        print(self.name.title() + " is now sitting.")
    def roll_over(self):
        """模拟小狗被命令时打滚"""
        print(self.name.title() + " rolled over!")

1. 方法 __init__()

类中的函数称为方法;开头和末尾各有两个下划线,避免Python默认方法与普通方法发生名称冲突。

def __init__(self, name, age):
#方法 __init__()定义成了包含三个形参:self、name和age

在这个方法的定义中,形参 self 必不可少,还必须位于其他形参的前面。Python调用这个 __init__() 方法来创建 Dog 实例时,将自动传入实参 self,因此我们不需要传递它。每个与类相关联的方法调用都自动传递实参 self ,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。每当我们根据 Dog 类创建实例时,都只需给最后两个形参( name age )提供值

 

self 为前缀的变量都可供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。 self.name = name 获取存储在形参 name 中的值,并将其存储到变量 name 中,然后该变量被关联到当前创建的实例。

像这样可通过实例访问的变量称为属性

# Dog类还定义了另外两个方法:sit()和roll_over()
def sit(self):
    """模拟小狗被命令时蹲下"""
def roll_over(self):
    """模拟小狗被命令时打滚"""

2. Python 2.7中创建类

Python 2.7中创建类时,需要做细微的修改——在括号内包含单词 object

class  ClassName (object):

9.1.2 根据类创建实例

创建一个表示特定小狗的实例:

class Dog():# 如前文创建Dog类所示
    snip --
my_dog = Dog('willie', 6)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")

我们通常可以认为首字母大写的名称(如Dog )指的是类,而小写的名称(如 my_dog )指的是根据类创建的实例

1. 访问属性

要访问实例的属性,可使用句点表示法。

my_dog.name

2. 调用方法

根据 Dog 类创建实例后,就可以使用句点表示法来调用 Dog 类中定义的任何方法。

 

3. 创建多个实例

可按需求根据类创建任意数量的实例。如

my_dog = Dog('willie', 6) # 第2个实例
your_dog = Dog('lucy', 3) # 第2个实例

9.2 使用类和实例

可以直接修改实例的属性,也可以编写方法以特定的方式进行修改。

9.2.1 创建另一个新的类

#创建另一个新的类
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 = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()

    # 添加了一个名为read_odometer()的方法,用于读取汽车的里程表
    def read_odometer(self):
        """打印一条指出汽车里程的消息"""
        print("This car has " + str(self.odometer_reading) + " miles on it.")

    # 下面的示例演示了一个名为 update_odometer() 的方法:
    def update_odometer(self, mileage):
        """将里程表读数设置为指定的值"""
        self.odometer_reading = mileage

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
#直接通过实例将该属性的值设置为23
my_new_car.odometer_reading = 23
my_new_car.update_odometer(23)
my_new_car.read_odometer()

9.2.2 给属性指定默认值

类中的每个属性都必须有初始值。

# 添加一个名为 odometer_reading 的属性,其初始值总是为0。
self.odometer_reading = 0

# 添加了一个名为read_odometer()的方法,用于读取汽车的里程表
def read_odometer(self):
    """打印一条指出汽车里程的消息"""
    print("This car has " + str(self.odometer_reading) + "miles on it.")

my_new_car.read_odometer()

9.2.3 修改属性的值

可以以三种不同的方式修改属性的值:直接通过实例进行修改;通过方法进行设置;通过方法进行递增(增加特定的值)。

1. 直接通过实例修改属性的值

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23 #直接通过实例将该属性的值设置为23
my_new_car.read_odometer()

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

class Car():
…….

# 下面的示例演示了一个名为 update_odometer() 的方法:
def update_odometer(self, mileage):
    """
    将里程表读数设置为指定的值
    禁止将里程表读数往回调

    """

    if mileage >= self.odometer_reading:
        self.odometer_reading = mileage
    else:
        print("You can't roll back an odometer!")

# 调用了 update_odometer(),实参23
my_new_car.update_odometer(23)

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

class Car():

    -- snip - -


    def update_odometer(self, mileage):

         -- snip -
     

    # 将属性值递增特定的量,而不是将其设置为全新的值
    def increment_odometer(self, miles):
        """将里程表读数增加指定的量"""
        self.odometer_reading += miles

# 创建了一辆二手车—— my_used_car 
my_used_car = Car('subaru', 'outback', 2013)
print(my_used_car.get_descriptive_name())
# 调用方法update_odometer() 并传入23500,将这辆二手车的里程表读数设置为23500
my_used_car.update_odometer(23500)
my_used_car.read_odometer()
# 调用 increment_odometer() 并传入100,以增加从购买到登记期间行驶的100英里
my_used_car.increment_odometer(100)
my_used_car.read_odometer()

9.3 继承

如果你要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。

9.3.1 子类的方法__init__()

创建子类的实例时,首先需要完成的任务是给父类的所有属性赋值。为此,子类的方法 __init__() 需要父类施以援手。

电动汽车是一种特殊的汽车,因此我们可以在前面创建的 Car类的基础上创建新类 ElectricCar,这样我们就只需为电动汽车特有的属性和行为编写代码。

# 电动汽车是一种特殊的汽车,因此我们可以在前面创建的 Car类的基础上创建新类 ElectricCar,
# 这样我们就只需为电动汽车特有的属性和行为编写代码。
# 创建子类时,父类必须包含在当前文件中,且位于子类前面。(见上节代码)
# 定义子类时,必须在括号内指定父类的名称
class ElectricCar(Car):
    """电动汽车的独特之处"""
    # 方法__init__()接受创建Car实例所需的信息
    def __init__(self, make, model, year):
        """初始化父类的属性"""
        # super()是一个特殊函数,帮助Python将父类和子类关联起来。
        super().__init__(make, model, year)
        # 添加新属性 self.battery_size ,并设置其初始值(如 70 )
        self.battery_size = 70
    # 添加了一个名为describe_battery()的方法,它打印有关电瓶的信息。
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a" + str(self.battery_size)+"-kWh battery.")

# 创建 ElectricCar 类的一个实例,并将其存储在变量 my_tesla 中
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()


# super()是一个特殊函数,帮助Python将父类和子类关联起来。
super().__init__(make, model, year)

9.3.2 Python 2.7中的继承

class Car(object):
def __init__(self, make, model, year):

-- snip --

class ElectricCar(Car):
def __init__(self, make, model, year):
super(ElectricCar, self).__init__(make, model, year)

-- snip --

函数 super() 需要两个实参:子类名和对象 self 。为帮助Python将父类和子类关联起来,这些实参必不可少。另外,在Python 2.7中使用继承时,务必在定义父类时在括号内指定 object

9.3.3 给子类定义属性和方法

让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。

def __init__(self, make, model, year):
    """初始化父类的属性"""
    # super()是一个特殊函数,帮助Python将父类和子类关联起来。
    super().__init__(make, model, year)
    # 添加新属性 self.battery_size ,并设置其初始值(如 70 )
    self.battery_size = 70
# 添加了一个名为describe_battery()的方法,它打印有关电瓶的信息。
def describe_battery(self):
    """打印一条描述电瓶容量的消息"""
    print("This car has a " + str(self.battery_size) + "-kWh battery.")

9.3.4 重写父类的方法

对于父类的方法,只要它不符合子类模拟的实物的行为,可对其进行重写。可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将只关注你在子类中定义的相应方法。

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

def ElectricCar(Car):

-- snip --

def fill_gas_tank():
"""电动汽车没有油箱"""
print("This car doesn't need a gas tank!")

Python将忽略 Car 类(父类)中的方法fill_gas_tank(),转而运行上述(子类)代码。

9.3.5 将实例用作属性

可以将大型类拆分成多个协同工作的小类。

不断给 ElectricCar 类添加细节时,我们可能会发现其中包含很多专门针对汽车电瓶的属性和方法。在这种情况下,我们可将这些属性和方法提取出来,放到另一个名为 Battery 的类中,并将一个 Battery 实例用作 ElectricCar 类的一个属性。

class Car():
    -- snip --
    
class Battery(): # 定义了一个名为 Battery 的新类,它没有继承任何类
    """一次模拟电动汽车电瓶的简单尝试"""
    def __init__(self, battery_size=70):
        """初始化电瓶的属性"""
        self.battery_size = battery_size
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")

class ElectricCar(Car):
    """电动汽车的独特之处"""
    def __init__(self, make, model, year):
        """初始化父类的属性,再初始化电动汽车特有的属性"""
        super().__init__(make, model, year)
        self.battery = Battery() # 添加了一个名为self.battery的属性
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()

self.battery = Battery() # 添加了一个名为self.battery的属性

这行代码让Python创建一个新的 Battery 实例,并将该实例存储在属性self.battery 中。每当方法 __init__() 被调用时,都将执行该操作;因此现在每个 ElectricCar 实例都包含一个自动创建的 Battery 实例。

my_tesla.battery.describe_battery()

这行代码让Python在实例 my_tesla 中查找属性 battery ,并对存储在该属性中的 Battery 实例调用方法 describe_battery()

9.3.6 模拟实物

 

9.4 导入类

Python允许你将类存储在模块中,然后在主程序中导入所需的模块。

9.4.1 导入单个类

from car import Car

import 语句让Python打开模块 car,并导入其中的 Car 类。

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

可根据需要在一个模块中存储任意数量的类。

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

可根据需要在程序文件中导入任意数量的类。从一个模块中导入多个类时,用逗号分隔了各个类。导入必要的类后,就可根据需要创建每个类的任意数量的实例。

from car import Car, ElectricCar

9.4.4 导入整个模块

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

import car # 导入整个模块
my_beetle = car.Car('volkswagen', 'beetle', 2016) # 句点表示法访问car中的Car类

9.4.5 导入模块中的所有类

from  module_name import *

不推荐使用这种导入方式

需要从一个模块中导入很多类时,最好导入整个模块,并使用 module_name.class_name 语法来访问类。

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

可将类存储在多个模块中时,一个模块中的类依赖于另一个模块中的类。可在前一个模块分别从每个模块中导入类。

9.5 Python 标准库

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

使用标准库中的任何函数和类,为此只需在程序开头包含的 import 语句。

如,要创建字典并记录其的键—值对的添加顺序,可使用模块collections中的OrderedDict 类。OrderedDict 实例的行为几乎与字典相同,区别只在于记录了键—值对的添加顺序。

from collections import OrderedDict

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值