目录
一、创建和使用类
二、根据类创建实例
2.1 访问属性
2.2 调用方法
2.3 创建多个实例
三、使用类和实例
3.1 Car类
3.2 给属性指定默认值
3.3 修改属性的值
3.3.1 直接修改属性的值
3.3.2 通过方法修改属性的值
3.3.3 通过方法对属性的值进行递增
四、继承
4.1 子类的方法 __init__()
4.2 Python 2.7中的继承
4.3 给子类定义属性和方法
4.4 重写父类的方法
4.5 将实例用作属性
五、导入类
5.1 导入单个类
5.2 在一个模块中存储多个类
5.3 从一个模块中导入多个类
5.4 导入整个模块
5.5 导入模块中的所有类
5.6 在一个模块中导入另一个模块
六、Python标准库
七、类编码风格
编写类时,定义一大类对象都有的通用行为,基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。
根据类来创建对象被称为实例化。
e.g 创建Dog类。根据Dog类创建的每个实例都将存储名字和年龄,赋予每条小狗蹲下(sit())和打滚(roll_over())的能力:
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!")
类的名称需要首字母大写。
1. 方法__init__()
类中的函数称为方法,有关函数的一切都适用于方法,唯一的差别在于调用方法的方式。
每次根据Dog类创建新实例时,Python都会自动运行方法__init__()。
形参self必不可少,且必须位于其他形参的前面;Python调用方法__init__()来创建Dog实例时,将自动传入实参self,每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。e.g 创建Dog实例时,Python将调用Dog类的方法__init__(),我们只需提供最后两个形参(name、age),self会自动传递。
2. self.name
以self为前缀的变量可供类中的所有方法使用,也可以通过类的任何实例来访问这些变量。self.name = name获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例。像这样,通过实例访问的变量称为属性。
class Dog():
---snip---
my_dog = Dog('while',6)
print("My dog's name is " + my_dog.name.title() +".")
print("My dog is " + str(my_dog.age) +" years old.")
句点表示法。
my_dog.name
my_dog.age
根据Dog类创建实例后,可以使用句点表示法来调用Dog类中定义的任何方法。
my_dog.sit()
my_dog.roll_over()
可根据需求创建任意数量的实例,前提是将每个实例都存储在不同的变量中,或占用列表或字典的不同位置。
修改实例的属性,可以直接修改也可以编写方法以特定的方式修改。
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或空字符串。在有些情况下,如设置默认值时,在方法__init__()内指定这种初始值时是可行的,如果对某个属性这样做了,就无需包含为它提供初始值的形参。
e.g 添加一个名为odometer_reading的属性,其初始值总是0,同时添加一个read_odometer()的方法,用于读取汽车的里程表。
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()
属性odometer_reading被赋予的初始值,没有包含在__init__()方法的形参中。
通过实例直接访问。
class Car():
---snip---
my_new_car = Car('audi','a4',2016)
print(my_new_car.get_descriptive_name())
# 直接使用句点表示法访问并设置汽车的属性odometer_reading,并将其设置为23
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
无需直接访问属性,可将值传递给一个方法,由它在内部进行更新。
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_olometer(23)
my_new_car.read_odometer()
对方法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!")
e.g 将属性值递增特定的量,而不是将其设置为全新的值。
假如我们购买了一辆二手车,且从购买到登记期间增加了100英里的里程。
class Car():
---snip---
def update_odometer(self, mileage):
---snip---
def increment_odometer(self,miles):
"""将里程表读数增加指定的量"""
if miles >= 0:
self.odometer_reading += miles
else:
print("You can't increase the minus odometer!"
my_used_car = Car('subaru','outback',2013)
print(my_used_car.get_descriptive_name())
my_used_car.update_odometer(23500)
my_used_car.read_odometer()
my_used_car.increment_odometer(100)
my_used_car.read_odometer()
e.g 模拟电动汽车。创建一个简单的ElecticCar类版本,具备Car类的所有功能。
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
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
""" 初始化父类的属性"""
super().__init__(make,model,year)
my_tesla = ElectricCar('tesla','model s',2016)
print(my_tesla.get_descriptive_name())
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---
让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法
e.g 添加电动汽车的特有属性(电瓶),以及一个描述该属性的方法;存储电瓶容量并编写一个打印电瓶描述的方法。
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','model s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
可以将类的一部分作为一个独立的类提取出来,即将一个大型类拆分成多个协同工作的小类。
e.g 将针对汽车电瓶的属性和方法,放到另一个类Battery()中,并将Battery实例用作ElectricCar类的一个属性。
class Car():
---snip---
class Battery():
"""模拟电动汽车的电瓶"""
def __init__(self, battery_size=70):
self.battery_size = battery
def describe_battery():
print("This car has a " + str(battery_size) +"-kWh battery.")
class ElectricCar():
def __init__(self, make, model, year):
super().__init__(make, model, year)
self.battery = Battery(80)
my_tesla = ElectricCar('Tesla','model s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
e.g 再给Battery类添加一个方法,根据其电瓶容量报告汽车的续航里程。
class Car():
--snip--
class Battery():
--snip--
def get_range(self):
"""打印一条消息,指出电瓶的续航里程"""
if self.battery_size == 70:
range = 240
elif self.battery_size ==85:
range = 270
message = "This car can go approximately " + str(range)
message +=" miles on a full charge."
print(message)
class ElectricCar(Car):
--snip--
my_tesla = ElectricCar('Tesla','model s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
可以将类Car 放在一个单独的文件car.py中,然后使用语句:
from car import Car
导入类Car。
import 后加不同的类名,导入不同的类。
from car import Car
from car import ElectricCar
from car import Battery
from car import ElectricCar
my_tesla = ElectricCar('tesla','model s',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
可根据需要在程序文件中导入任意数量的类,使用逗号,分隔各个类。
from car import Car,ElectricCar
使用句点表示法访问需要的类。
import car
my_car = car.Car('audi','a4',2016)
要导入模块中的每个类,使用*
from module_name import *
e.g 将Car类存储在car.py模块中,将ElectricCar和Battery类存储在另一个模块electric_car.py中。
from car import Car
class Battery():
--snip--
class ElectricCar(Car):
--snip--
e.g 创建一个Die类,它包含一个名为sides的属性,该属性的默认值为6,编写一个名为roll_die()的方法,它位于1和骰子面数之间的一个随机数,创建一个6面的骰子,掷10次。创建一个10面和一个20面的骰子,并将他们都掷10次。
from random import randint
class Die():
def __init__(self, sides=6):
self.sides = sides
def roll_die(self):
print(str(randint(1,self.sides)))
my_die_6 = Die()
print("\n Roll Die-6:")
for i in range(0,10):
my_die_6.roll_die()
my_die_10 = Die(10)
print("\nRoll Die-10:")
for i in range(0,10):
my_die_10.roll_die()
my_die_20 =Die(20)
print('\nRoll Die-20:')
for i in range(0,10):
my_die_20.roll_die()