Python编程 从入门到实践——第9章 类

9.1 创建和使用类

根据类来创建对象称为实例化。

9.1.1 创建Dog类

# dog.py
# 在Python中,首字母大写的名称指的是类
class Dog:
	"""一次模拟小狗的简单尝试"""
	def _init_(self, name, age):
		"""初始化属性name和age"""
		self.name = name
		self.age = age

	def sit(self):
		"""模拟小狗收到命令时做下"""
		print(f"{self.name} is now sitting.")

	def roll_over(self):
		"""模拟小狗收到命令时打滚"""
		print(f"{self.name} rolled over!")

方法_init()_
(1)类中的函数称为方法
(2)当你根据Dog类创建新实例时,Python都会自动运行它。
(3)在这个方法名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。
(4)在这个方法的定义中,形参self必不可少,而且必须位于其他形参的前面。Python调用这个方法来创建Dog实例时,将自动传入实参self。每个实例相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
(5)以self为前缀的变量可供类中的所有方法使用,可以通过类的任何实例来访问,称为属性。

9.1.2 根据类创建实例

class Dog:
	"""一次模拟小狗的简单尝试"""
	def _init_(self, name, age):
		"""初始化属性name和age"""
		self.name = name
		self.age = age

	def sit(self):
		"""模拟小狗收到命令时做下"""
		print(f"{self.name} is now sitting.")

	def roll_over(self):
		"""模拟小狗收到命令时打滚"""
		print(f"{self.name} rolled over!")

my_dog = Dog('Willie', 6)
# 访问属性——句点表示法
print(f"My dog's name is {my_dog.name}.")
print(f"My dog is {my_dog.age} years old.")
# 调用方法
my_dog.sit()
my_dog.roll_over()
# 创建多个实例
your_dog = Dog('Lucy', 3)
print(f"Your dog's name is {your_dog.name}.")
print(f"Your dog is {your_dog.age} years old.")
your_dog.sit()
your_dog.roll_over()

动手试一试

9.2 使用类和实例

9.2.1 Car类

# car.py
class Car:
	"""一次模拟汽车的简单尝试"""
	def _init_(self, make, model, year):
		"""初始化描述汽车的属性"""
		self.make = make
		self.model = model
		self.year = year

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

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

9.2.2 给属性指定默认值

创建实例时,有些属性无需通过形参来定义,可在方法_init_()中为其指定默认值。

# 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 = f"{self.year} {self.make} {self.model}"
		return long_name.title()

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

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

9.2.3 修改属性的值

1、直接修改属性的值

my_new_car.odometer_reading = 23
my_new_car.read_odometer()

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 = f"{self.year} {self.make} {self.model}"
		return long_name.title()

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

	def update_odometer(self, mileage):
		"""
		将里程表读书设置为指定的值
		禁止价格里程表读数往回调
		"""
		if mileage >= self.odometer_readig:
			self.odometer_reading = mileage
		else:
			print("You can't roll back an odometer!")

my_new_car = Car('audi', 'a4', '2009')
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(23)
my_new_car.read_odometer()

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

# 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 = f"{self.year} {self.make} {self.model}"
		return long_name.title()

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

	def update_odometer(self, mileage):
		"""
		将里程表读书设置为指定的值
		禁止价格里程表读数往回调
		"""
		if mileage >= self.odometer_readig:
			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', '2009')
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(23)
my_new_car.read_odometer()
my_new_car.increment_odometer(100)
my_new_car.read_odometer()

动手试一试

9.3 继承

编写类时,并非总是要从空白开始。如果要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,将自动获得另一个类的所有属性和方法。原有的类称为父类,而新类称为子类。子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法。

9.3.1 子类的方法_init_()

在既有类的基础上编写新类时,通常要调用父类的方法_init_()。这将初始化在父类_init_()方法中定义的所有属性,从而让子类包含这些属性。

# eletric_car.py
# 定义子类时,必须在圆括号内指定父类的名称
class EletricCar(Car):
	"""电动汽车的独特之处"""
	def _init_(self, make, model, year):
		"""初始化父类的属性"""
		# 让Python调用Car类的方法_init_(),父类也称为超类
		super()._init_(make, model, year)

my_tesla = EletricCar('tesla', 'model s', 2019)
print(my_tesla.get_description_name())

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

9.3.2 给子类定义属性和方法

class EletricCar(Car):
	"""电动汽车的独特之处"""
	def _init_(self, make, model, year):
		"""
		初始化父类的属性
		再初始化电动汽车特有的属性
		"""
		# 让Python调用Car类的方法_init_(),父类也称为超类
		super()._init_(make, model, year)
		self.battery_size = 75

	def describe_battery(self):
		"""打印一条描述电瓶容量的消息"""
		print(f"This car has a {self.battery_size}-kWh battery.")
		
my_tesla = EletricCar('tesla', 'model s', 2019)
print(my_tesla.get_description_name())
my_tesla.describe_battery()

9.3.3 重写父类的方法

可在子类中定义一个与要重写的父类方法同名的方法。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

9.3.4 将实例用作属性

class Battery:
	"""一次模拟电动汽车电瓶的简单尝试"""
	def _init_(self, battery_size=75):
		"""初始化电瓶的属性"""
		self.battery_size = battery_size

	def describe_battery(self):
		"""打印一条描述电瓶容量的消息"""
		print(f"This car has a {self.battery_size}-kWh battery.")

	def get_range(self):
		"""打印一条消息,指出电瓶的续航里程"""
		if self.battery_size == 75:
			range = 260
		elif self.battery_size == 100:
			range = 315
		print(f"This car can go about {range} miles on a full charge.")

class EletricCar(Car):
	"""电动汽车的独特之处"""
	def _init_(self, make, model, year):
		"""
		初始化父类的属性
		再初始化电动汽车特有的属性
		"""
		# 让Python调用Car类的方法_init_(),父类也称为超类
		super()._init_(make, model, year)
		# 让Python创建一个新的Battery实例。每当方法_init_()被调用时,都将执行该操作,因此现在每个EletricCar实例都包含一个自动创建的Battery实例
		self.battery = Battery()

	def describe_battery(self):
		"""打印一条描述电瓶容量的消息"""
		print(f"This car has a {self.battery_size}-kWh battery.")
		
my_tesla = EletricCar('tesla', 'model s', 2019)
print(my_tesla.get_description_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

9.3.5 模拟实物

动手试一试

9.4 导入类

允许将类存储在模块中,然后在主程序中导入所需的模块。

9.4.1 导入单个类

# 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 = f"{self.year} {self.make} {self.model}"
		return long_name.title()

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

	def update_odometer(self, mileage):
		"""
		将里程表读书设置为指定的值
		禁止价格里程表读数往回调
		"""
		if mileage >= self.odometer_readig:
			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', 2019)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()

9.4.2 在一个模块中存储多个类

# my_electric_car.py
# 将Car、Battery、ElectricCar类均放在car.py文件中
from car import EletricCar

my_tesla = EletricCar('tesla', 'model s', 2019)
print(my_tesla.get_description_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

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

# my_cars.py
from car import Car, ElectricCar

9.4.4 导入整改模块

# my_cars.py
import car

my_beetle = car.Car('volkswagen', 'beetle', 2019)
print(my_beetle.get_descriptive_name())

my_tesla = car.ElectricCar('tesla', 'roadster', 2019)
print(my_tesla.get_descriptive_name())

9.4.5 导入模块中的所有类

from module_name import *

不推荐使用这种导入方式,原因:
(1)如果只看文件开头的import语句,就能清楚地知道程序使用了哪些类,将大有裨益。然而这种导入方式没有明确地指出使用了模块中的哪些类
(2)这种方式还可能引发名称方面的迷惑。如果不小心导入了一个与程序文件中其他东西同名的类,将引发难以诊断的错误

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

有时,将类分散到多个模块中,可以在一个模块中导入其必要的类

9.4.7 使用别名

from electric_car import ElectricCar as EC
my_tesla = EC('tesla', 'roadster', 2019)

9.4.8 自定义工作流程

动手试一试

9.5 Python标准库

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

>>> from random import randint
# 将两个整数作为参数,并随机返回一个位于这两个整数之间(包含)的整数
>>> randint(1, 6)
>>> from random import choice
# 将一个列表或元组作为参数,并随机返回一个元素
>>> players = ['charles', 'martina', 'michael', 'florence', 'eli']
>>> first_up = choice(players)
>>> first_up
'florence'

动手试一试

9.6 类编码风格

1、类名采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不是使用下划线。
2、实例名和模块名都采用小写格式,并在单词之间加上下划线。
3、对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式规定。每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。
4、在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。
5、需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import语句,再添加一个空行,然后编写导入你自己编写的模块的import语句。

9.7 小结

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值