读书笔记「Python编程:从入门到实践」_9.类

9.1 创建和使用类

  面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。

  OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

  把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。

  编写时,你定义一大类对象都有的通用行为。

  基于类创建对象 时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。

  根据类来创建对象被称为实例化 ,这让你能够使用类的实例。

  9.1.1 创建Dog类 

class Dog(): 
    #在Python中,首字母大写的名称指的是类。这个类定义中的括号是空的,因为我们要从空白创建这个类。
    #class ClassName(object):在Python 2.7中创建类时,需要做细微的修改——在括号内包含单词object
    """一次模拟小狗的简单尝试""" 
    #我们编写了一个文档字符串,对这个类的功能作了描述。
    def __init__(self, name, age):
        #方法__init__() 是一个特殊的方法,每当你根据Dog 类创建新实例时,Python都会自动运行它。
        #在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。
        #方法__init__() 并未显式地包含return 语句,但Python自动返回一个表示这条小狗的实例
        """初始化属性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!")

  9.1.2 根据类创建实例

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

  句点表示法在Python中很常用,这种语法演示了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.")

9.2 使用类和实例

  9.2.1 Car类
  9.2.2 给属性指定默认值
  9.2.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 = 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):
        """
        将里程表读数设置为指定的值
        禁止将里程表读数往回调
        """
        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

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()
#通过方法修改属性的值
my_new_car.update_odometer(500)
my_new_car.read_odometer()
my_new_car.update_odometer(50)
my_new_car.read_odometer()
#通过方法对属性的值进行递增
my_new_car.increment_odometer(10)
my_new_car.read_odometer()
2016 Audi A4
This car has 23 miles on it.
This car has 500 miles on it.
You can't roll back an odometer!
This car has 500 miles on it.

9.3 继承

  9.3.1 子类的方法__init__()

  9.3.2 Python 2.7中的继承

  9.3.3 给子类定义属性和方法

  9.3.4 重写父类的方法

  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):
        """
        将里程表读数设置为指定的值
        禁止将里程表读数往回调
        """
        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
    def fill_gas_tank(self):
        """加满油"""
        print("Now gas tank is full!")
View Code
from car import Car
#让Python打开模块car ,并导入其中的Car 类。这样我们就可以使用Car 类

class ElectricCar(Car):       #必须在括号内指定父类的名称
    """电动汽车的独特之处"""
    def __init__(self, make, model, year):
        """初始化父类的属性"""
        super().__init__(make, model, year) #supper是一个特殊函数,帮助Python将父类和子类关联起来
        #Python 2.7中使用继承时 需要两个实参:子类名和对象self
        #super(ElectricCar, self).__init__(make, model, year)  
        #给子类定义属性和方法
        self.battery_size = 400
    #给子类定义属性和方法
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")
    #重写父类的方法,与要重写的父类方法同名。这样,Python将不会考虑这个父类方法
    def fill_gas_tank(self):
        """电动汽车没有油箱"""
        print("This car doesn't need a gas tank!")


my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.fill_gas_tank()
my_tesla.describe_battery()
2016 Tesla Model S
This car doesn't need a gas tank!
This car has a 400-kWh battery.

  9.3.5 将实例用作属性

from car import Car
#让Python打开模块car ,并导入其中的Car 类。这样我们就可以使用Car 类
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 = Battery()

my_tesla = ElectricCar('tesla', 'model s', 2016)
my_tesla.battery.battery_size=80
my_tesla.battery.describe_battery()
This car has a 80-kWh battery.

  9.3.6 模拟实物

  从较高的逻辑层面(而不是语法层面)考虑;你考虑的不是Python,而是如何使用代码来表示实物。

  到达这种境界后,你经常会发现,现实世界的建模方法并没有对错之分。有些方法的效率更高,但要找出效率最高的表示法,需要经过一定的实践。

  只要代码像你希望的那样运行,就说明你做得很好!即便你发现自己不得不多次尝试使用不同的方法来重写类,也不必气馁;要编写出高效、准确的代码,都得经过这样的过程。

9.4 导入类
  9.4.1 导入单个类

  from car import Car

  import 语句让Python打开模块car ,并导入其中的Car 类。这样我们就可以使用Car 类了,就像它是在这个文件中定义的一样
  9.4.2 在一个模块中存储多个类

 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):
        """
        将里程表读数设置为指定的值
        禁止将里程表读数往回调
        """
        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
    def fill_gas_tank(self):
        """加满油"""
        print("Now gas tank is full!")

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 = Battery()
View Code

 mycar.py

from car import ElectricCar

my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
2016 Tesla Model S
This car has a 70-kWh battery.

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

from car import Car, ElectricCar

my_beetle = Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
2016 Volkswagen Beetle
2016 Tesla Roadster

  9.4.4 导入整个模块

  使用语法 module_name.class_name 访问需要的类

import car

my_beetle = car.Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = car.ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
2016 Volkswagen Beetle
2016 Tesla Roadster

  9.4.5 导入模块中的所有类

  要导入模块中的每个类,可使用下面的语法:from module_name import *

  不推荐

  ① 没有明确地指出你使用了模块中的哪些类。

  ② 类名可能重复

from car import *

my_beetle = Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())

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

 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):
        """
        将里程表读数设置为指定的值
        禁止将里程表读数往回调
        """
        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
    def fill_gas_tank(self):
        """加满油"""
        print("Now gas tank is full!")
View Code

 electricCar.py

from car import Car
#让Python打开模块car ,并导入其中的Car 类。这样我们就可以使用Car 类
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 = Battery()
View Code

 myCar.py

from car import Car
from electricCar import ElectricCar

my_beetle = Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
2016 Volkswagen Beetle
2016 Tesla Roadster

9.4.7 自定义工作流程

  一开始应让代码结构尽可能简单。先尽可能在一个文件中完成所有的工作,确定一切都能正确运行后,再将类移到独立的模块中。
  如果你喜欢模块和文件的交互方式,可在项目开始时就尝试将类存储到模块中。先找出让你能够编写出可行代码的方式,再尝试让代码更为组织有序。

9.5 Python标准库

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

  下面来看模块collections 中的一个类——OrderedDict 。来创建一个空的有序字典

from collections import OrderedDict
favorite_languages = OrderedDict()
favorite_languages['jen'] = 'python'
favorite_languages['sarah'] = '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() + ".")
Jen's favorite language is Python.
Sarah's favorite language is C.
Edward's favorite language is Ruby.
Phil's favorite language is Python.

9.6 类编码风格

  类名应采用驼峰命名法 ,即将类名中的每个单词的首字母都大写,而不使用下划线。

  实例名和模块名都采用小写格式,并在单词之间加上下划线。 ※抱歉例子中的模块名命名不规范

  对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。

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

  可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。

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

原文地址:https://www.cnblogs.com/changxinblog/p/9987024.html