9. 类

创建和使用类

创建Dog类

在Python中,首字母大写的名称指的是类

class Dog():
    """一次模拟小狗的简单尝试"""

    def __init__(self, name, age):
        """初始化属性name和age"""
        self.name = name
        self.age = age

    def sit(self):
        """模拟小狗呗命令时蹲下"""
        print(self.name.title() + " is now sitting.")

    def roll_over(self):
        """模拟小狗被命令时打滚"""
        print(self.name.title() + " rolled over!")

类定义中的括号是空,表明要从空白创建这个类;

类中的函数称为方法;

方法__ init __():

是一个特殊的方法,每当根据Dog类创建新实例时,Python都会自动运行它;

形参self必不可少,还必须位于其他形参的前面;

Python调用这个方法,将自动传入实参self,每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法;

self.name:

以self为前缀的变量都可供类中所有方法使用,还可以通过类的任何实例来访问这些变量;

根据类创建实例

方法__ init __()创建了一个表示特定小狗的示例,并使用我们提供的值来设置属性name和age。

方法__ init __()并未显式地包含return语句,但Python自动返回一个表示小狗的实例

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.")

访问属性:

访问实例的属性,可使用句点表示法 my_dog.name

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

my_dog = Dog('willie', 6)
my_dog.sit()
my_dog.roll_over()

创建多个实例:

my_dog = Dog('willie', 6)
your_dog = Dog('lucy', 3)

print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")
my_dog.sit()

print("Your dog's name is " + your_dog.name.title() + ".")
print("Your dog is " + str(your_dog.age) + " years old.")
your_dog.sit()

每个实例都存储在不同的变量中,或占用列表或字典的不同位置

使用类和实例

类编写好后,大部分时间会花在使用根据类创建的实例上

Car类

class Car():
    """一次模拟汽车的简单尝试"""

    def  __init__(self, make, model, year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year

    def get_descriptive_name(self):
        """返回整洁的描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())

给属性指定默认值

类中的每个属性都必须有初始值,哪怕这个值是0或空字符串

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 = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()

    def read_odometer(self):
        """打印一条指出汽车里程的消息"""
        print("This car has " + str(self.odometer_reading) + "miles on it")

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

修改属性的值

三种方法:直接通过实例修改;通过方法进行设置;通过方法进行递增

1.直接修改属性的值

class Car():
    --snip--
    
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading=23
my_new_car.read_odometer()

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

class Car():
    --snip--
    
    def update_odometer(self, mileage):
        """将里程表读数设置为指定的值"""
        self.odometer_reading = mileage
        
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(23)
my_new_car.read_odometer()

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

class Car():
    --snip--
    
    def update_odometer(self, mileage):
        --snip--
        
    def increment_odometer(self, miles):
        self.odometer_reading += miles
        
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(23500)
my_new_car.read_odometer()
my_new_car.increment_odometer(100)
my_new_car.read_odometer()

继承

如果要编写的类是另一个现成类的特殊版本,可使用继承。

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

原有的类称为父类,而心类称为子类;

子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法

子类的方法__ init __()

创建子类的实例时,Python首先需要完成的任务是给父类的所有属性赋值

class Car():
    """一次模拟汽车的简单尝试"""
    --snip--
    
    def __init__(self, make, model, year):
        --snip--
    
    def get_descriptive_name(self):
        --snip--
        
    def read_odometer(self):
        --snip--
        
    def update_odometer(self, mileage):
        --snip--
        
    def increment_odometer(self, miles):
        --snip--
        
class ElectricCar(Car):
    """电动汽车的独特之处"""
    
    def __init__(self, make, model, year):
        """初始化父类的属性"""
        super().__init__(make, model, year)
        
my_tesla = ElectricCar('tesla', 'models', 2016)
print(my_tesla.get_descriptive_name())

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

super():

特殊函数,帮助Python将父类和子类关联起来,这行代码让Python调用父类的方法__ init __()

给子类定义属性和方法

class Car():
    --snip--
    
class ElectricCar(Car):
    
    def __init__(self, make, model, year):
        """
        初始化父类的属性,再初始化电动汽车特有的属性
        """
        super().__init__(make, model, year)
        self.battery_size = 70
        
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")
        
my_tesla = ElectricCar('tesla', 'models', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()

重写父类的方法

假设Car类有一个名为fill_gas_tank()的方法,对全自动电动汽车来说没有意义,可以在子类中重写它

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

调用子类的fill_gas_tank()方法,Python将忽略父类中的方法fill_gas_tank()

将实例用作属性

class Car():
    --snip--
    
class 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_size = battery()
        
my_tesla = ElectricCar('tesla', 'models', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.Battery.describe_battery() 

模拟实物

如何使用代码来表示实物

导入类

导入单个类

使主程序变得整洁而易于阅读

car.py

"""一个可用于表示汽车的类"""

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 = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()

    def read_odometer(self):
        """打印一条指出汽车里程的消息"""
        print("This car has " + str(self.odometer_reading) + "miles on it")

    def update_odometer(self, mileage):
        """将里程表读数设置为指定的值"""
        self.odometer_reading = mileage

    def increment_odometer(self, miles):
        """将里程表读数增加指定的量"""
        self.odometer_reading += miles

my_car.py

from car import Car

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading=23
my_new_car.read_odometer()

在一个模块中存储多个类

car.py

"""一组表示燃油汽车和电动汽车的类"""

class Car():
    --snip--
    
class Battery():
    --snip--
    
class ElectricCar(Car):
    --snip--

my_electricCar.py

from car import ElectricCar

my_tesla = ElectricCar('tesla', 'models', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery() 

从一个模块中导入多个类

from car import Car, ElectricCar

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())

my_tesla = ElectricCar('tesla', 'models', 2016)
print(my_tesla.get_descriptive_name())

导入整个模块

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

创建类实例的代码都包含模块名,因此不会与当前文件使用的任何名称发生冲突

import car

my_new_car = car.Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())

my_tesla = car.ElectricCar('tesla', 'models', 2016)
print(my_tesla.get_descriptive_name())

导入模块中的所有类

from module_name import *

不推荐这种方式

首先,这种导入方式没有明确的指出你使用了模块中的哪些类

其次,可能不小心导入一个与程序文件中其他东西同名的类

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

为了避免模块太大,将类分散到多个模块中,或在同一个模块中存储不相关的类

car.py

"""一个可用于表示汽车的类"""

class Car():
    --snip--

electric_car.py

"""一组可用于表示电动汽车的类"""

from car import Car

class Battery():
    --snip--
    
class ElectricCar(Car):
    --snip--

my_cars.py

from car import Car
from electric_car import ElectricCar

my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())

my_tesla = ElectricCar('tesla', 'models', 2016)
print(my_tesla.get_descriptive_name())

自定义工作流程

先尽可能在一个文件中完成所有的工作,确定要一切都能正确运行后,再将类移到独立的模块中

或者项目开始时就尝试将类存储到模块中

先找出能够编写可行代码的方式,再尝试让代码更为组织有序

Python标准库

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

可使用标准库中的任何函数和任何类

示例:模块collections中的一个类OrderedDict

作用:创建字典并记录其中的键-值对的添加顺序

from collections import OrderedDict

favorite_languages = OrderedDict() #创建一个空的有序字典

favorite_languages['jen'] = 'python'
favorite_languages['sarsh'] = 'c'
favorite_languages['edward'] = 'ruby'
favorite_languages['phil'] = 'python'

for name, language in favorite_languages.items():
    print(name.title() + "'s favorite language is " + language.title() + ".")

类编码风格

类名采用驼峰命名法:类名中每个单词的首字母大写,不使用下划线

实例名和模块名都采用小写格式,并在单词之间加上下划线

每个类,紧跟再类定义后面包含一个文档字符串,简要描述类的功能

每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述

可使用空行来组织代码,但不能滥用

类中,使用一个空行来分隔方法

模块中,使用两个空行来分隔类

需要同时写入标准库中的模块和自己编写的模块时,先写编写导入标准库模块的import语句,再添加一个空行,然后编写导入自己编写的模块的import语句

posted @ 2021-11-25 13:09  KYZH  阅读(91)  评论(0编辑  收藏  举报