类
1. 创建和使用类
1.1 创建一个简单类
class Dog():
"""A simple attempt to model a dog."""
def __init__(self, name, age): # 赋予Dog类name和dog属性
"""Initialize name and age attributes."""
self.name = name
self.age = age
def sit(self):
"""Simulate a dog sitting in response to a command."""
print(self.name.title() + " is now sitting.")
def roll_over(self):
"""Simulate rolling over in response to a command."""
print(self.name.title() + " rolled over!")
1) 首先习惯性地,类名首字母大写,类中的函数即方法全小写
2) 一般来讲,定义类时,包括属性初始化方法__init__()和其他方法
3)初始化方法的下划线是避免与python默认方法发生冲突
4)关于形参self,首先每个方法都必须包含self形参,而且必须位于其他形参前面。因为python在调用__init__()创建实例时, 将自动传入实参self,每个与类关联的方法调用都自动传入实参self,它是一个指向实例本身的作用,让实例能够访问类中 的属性和方法。而当根据Dog类创建实例时,都只需要给出self后两个形参的值
5)所有self为前缀的变量都可以供类中的方法使用
1.2 根据类创建实例
下面根据上面的Dog类创建实例
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.")
python使用实参'willie'和6以及调用__init__()方法创建my_dog实例,创建实例后使用instance_name.attribute_name格式来访 问属性
而访问其他方法可以用,创建实例后,可以用这种句点表示法访问类中的所有方法
my_dog.__init__('lucy', 3) # 重新赋予Dog类的name和age属性
my_dog.sit()
my_dog.roll_over()
1.3 默认和修改属性值
"""A class that can be used to represent a car."""
class Car():
"""A simple attempt to represent a car."""
def __init__(self, manufacturer, model, year):
"""Initialize attributes to describe a car."""
self.manufacturer = manufacturer
self.model = model
self.year = year
self.odometer_reading = 0 #默认属性值
def get_descriptive_name(self):
"""Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.manufacturer + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self, mileage): #使用方法修改属性值
"""
Set the odometer reading to the given value.
Reject the change if it attempts to roll the odometer back.
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
my_new_car.odometer_reading = 23 #直接修改属性值
修改属性值包括直接修改和通过方法修改,如上
2. 继承
如果要编写一个现成类的特殊版本,就可以使用继承,该特殊版本的类称为子类,现成类称为父类。子类继承了父类所有的属性和方法,并且还可以定义自己的属性和方法
2.1 子类的方法__init__()
创建子类的实例时,首先就是要给父类的所有属性赋值,因此子类的__init__()需要父类施以援手,如下
并且创建子类时,父类必须在当前文件中,或者采用后面导入类的方法,且位于子类的前面
"""A class that can be used to represent a car."""
class Car():
"""A simple attempt to represent a car."""
def __init__(self, manufacturer, model, year):
"""Initialize attributes to describe a car."""
self.manufacturer = manufacturer
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
"""Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.manufacturer + ' ' + self.model
return long_name.title()
def read_odometer(self):
"""Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self, mileage):
"""
Set the odometer reading to the given value.
Reject the change if it attempts to roll the odometer back.
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
"""Add the given amount to the odometer reading."""
self.odometer_reading += miles
# 定义父类时为了书写的简洁,用以下方式省略
class Car():
""" snip """
class ElectricCar(Car): # 定义子类,括号要包含父类名称
def __init__(self,manufacturer, model, year):
super(). __init__(self, manufacturer, model, year) # 父类也称为superclass
my_tesla = ElectricCar('tesla', 'model s', 2016) # 创建子类的实例
print(my_tesla.get_descriptive_name()) # 调用子类的方法
2.2 给子类定义新的属性和方法
class Car():
""" snip """
class ElectricCar(Car):
def __init__(self,manufacturer, model, year):
super(). __init__(self, manufacturer, model, year)
self.battery_size = 70 # 添加新属性并默认值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() # 调用子类添加的新方法
2.3 重写父类的方法
即对于父类中的方法可能不适用于子类,这时候在子类中可定义一个方法与要父类的方法同名,即重写,例如假设父类Car中 有个fill_gas_tank()方法,而子类ElectricCar模拟的电动车没有gas tank这一选项,此时可进行如下重写
def ElectricCar(Car):
""" snip """ # 这部分内容跳过,见上文
def fill_gas_tank():
"""电动汽车没有油箱"""
print("This car doesn't need a gas tank!")
2.4 将实例作用于属性
结合2.2定义的新属性battery_size,本部分将定义一个Battery类并创建实例作用于Electric的属性
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 = Battery()
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery() # 调用实例my_telsa属性battery中的describe_battery方法
3. 导入类
本部分跟之前的导入模块很相似,如下文代码中的四种情况,快速带过,
同样是先创建一个car.py(该文件的内容见上文或者原书),里面定义Car类,然后在当前文件夹新建一个my_car.py,来导入 car.py中的类
my_car.py
from car import Car # 导入car.py中的Car类
#from car import Car,ElectricCar # 多个类之间用逗号隔开
#import car # 导入整个模块
#from car import * # 导入模块中所有类
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()