《Python编程从入门到实践》第九章

#第九章 类


#9.1 创建和使用类

#创建Dog类
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两边是两个下划线!!!
'''
1. 方法__init__()
__init__()是一个特殊的方法,
每当你根据Dog类创建新实例时,Python都会自动运行它。
在这个方法的名称中,开头和末尾各有两个下划线,
这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。

我们将方法__init__()定义成了包含三个形参:self、name和age。
在这个方法的定义中,形参self必不可少,还必须位于其他形参的前面。

Python调用这个__init__()方法来创建Dog实例时,将自动传入实参self。
每个与类相关联的方法调用都自动传递实参self,
它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
'''

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's name is Willie. 
My dog is 6 years old. 
'''

my_dog.sit() 
my_dog.roll_over() 

'''
Willie is now sitting. 
Willie rolled 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("\nYour dog's name is " + your_dog.name.title() + ".") 
print("Your dog is " + str(your_dog.age) + " years old.") 
your_dog.sit() 

'''
My dog's name is Willie. 
My dog is 6 years old. 
Willie is now sitting. 
Your dog's name is Lucy. 
Your dog is 3 years old. 
Lucy is now sitting. 
'''

#9.2 使用类和实例

#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()) 

'''
2016 Audi A4 
'''

#给属性指定默认值
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() 

'''
2016 Audi A4 
This car has 0 miles on it. 
'''

#修改属性的值

#直接修改属性的值
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.odometer_reading = 23 
my_new_car.read_odometer() 

'''
2016 Audi A4 
This car has 23 miles on it. 
'''

#通过方法修改属性的值
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 

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()

'''
2016 Audi A4 
This car has 23 miles on it. 
'''

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

#通过方法对属性的值进行递增
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_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()

'''
2013 Subaru Outback 
This car has 23500 miles on it. 
This car has 23600 miles on it.
'''


#9.3 继承

#子类的方法__init__()
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()) 

'''
创建子类时,父类必须包含在当前文件中,且位于子类前面
定义子类时,必须在括号内指定父类的名称
方法__init__()接受创建Car实例所需的信息
super()是一个特殊函数,帮助Python将父类和子类关联起来
'''

'''
2016 Tesla Model S 
'''

#给子类定义属性和方法
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): 
	"""Represent aspects of a car, specific to electric vehicles.""" 

	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() 

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

#假设Car类有一个名为fill_gas_tank()的方法,它对全电动汽车来说毫无意义,因此你想重写它。
class ElectricCar(Car): 
	"""Represent aspects of a car, specific to electric vehicles.""" 

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

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


#将实例用作属性
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 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): 
	"""Represent aspects of a car, specific to electric vehicles.""" 

	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() 

'''
在ElectricCar类中,我们添加了一个名为self.battery的属性
因此现在每个ElectricCar实例都包含一个自动创建的Battery实例
'''

'''
2016 Tesla Model S 
This car has a 70-kWh battery. 
'''



#9.4 导入类

#在一个模块中存储单个类
#导入单个类
'''
下面来创建一个只包含Car类的模块

文件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
		

文件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() 

输出结果:
2016 Audi A4 
This car has 23 miles on it. 

'''

#在一个模块中存储多个类
#从一个模块中导入多个类
'''

文件car.py

"""一组用于表示燃油汽车和电动汽车的类""" 
class Car(): 
	--snip-- 
 
class Battery(): 
	"""一次模拟电动汽车电瓶的简单尝试""" 
	def __init__(self, battery_size=60): 
		"""初始化电瓶的属性""" 
		self.battery_size = battery_size 
	
	def describe_battery(self): 
		"""打印一条描述电瓶容量的消息""" 
		print("This car has a " + str(self.battery_size) + "-kWh battery.") 
 
	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): 
	"""模拟电动汽车的独特之处""
	def __init__(self, make, model, year): 
		""" 
		初始化父类的属性,再初始化电动汽车特有的属性
		""" 
		super().__init__(make, model, year) 
		self.battery = Battery() 

文件my_car.py

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 


'''


#导入整个模块
'''

import car
我们导入了整个car模块

'''

#导入模块中的所有类
'''

from module_name import * 

'''

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

注意导入顺序

'''