《Python编程:从入门到实践》第9章-类 习题

9-1 餐馆

创建一个名为Restaurant的类,其方法__init__()设置两个属性:restaurant_name和cuisine_type。创建一个名为describe_restaurant()的方法和一个名为open_restaurant()的方法,其中前者打印前述两项信息,而后者打印一条消息,指出餐馆正在营业。
根据这个类创建一个名为restaurant的实例,分别打印其两个属性,再调用前述的两个方法。

class Restaurant():
	"""docstring for Restaurant"""
	
	def __init__(self, restaurant_name, cuisine_type):
		self.name = restaurant_name
		self.type = cuisine_type
		#self.name---变量(可以通过实例访问的变量称为属性)
		#restaurant_name---形参

	def describe_restaurant(self):
		print("The restaurant's name is " + self.name.title())
		print("The restaurant has " + str(self.type) + " cuisine types.")
		#该方法打印了前述两项信息

	def open_restaurant(self):
		print("The restaurant is open now.")
		#该方法打印一条消息,指出餐馆正在营业

restaurant = Restaurant('mamala', 10)
print(restaurant.name.title() + ' ' + str(restaurant.type)) 
#打印其两个属性

restaurant.describe_restaurant()
restaurant.open_restaurant()
#根据要求调用前述两个方法。

区分变量和实参:以self为前缀的变量都可供类中的所有方法使用。还可以通过类的任何实例来访问这些变量。

self.name = restaurant_name获取储存在形参restaurant_name中的值,并将其储存到变量name中,然后该变量被关联到当前创建的实例。

像这样可通过实例访问的变量称为属性

build

Mamala 10
The restaurant's name is Mamala
The restaurant has 10 cuisine types.
The restaurant is open now.
[Finished in 2.0s]

9-2 三家餐馆

根据你为完成练习9-1而编写的类创建三个实例,并对每个实例调用方法describe_restaurant。

类的主体不变 增加两个实例 代码如下

restaurant_a = Restaurant('mamala', 10)
restaurant_b = Restaurant("jason's library", 8)
restaurant_c = Restaurant("bread talk", 4)

restaurant_a.describe_restaurant()
restaurant_b.describe_restaurant()
restaurant_c.describe_restaurant()

build


The restaurant's name is Mamala
The restaurant has 10 cuisine types.

The restaurant's name is Jason'S Library
The restaurant has 8 cuisine types.

The restaurant's name is Bread Talk
The restaurant has 4 cuisine types.
[Finished in 0.5s]

9-3用户

创建一个名为User的类,其中包含属性first_name和last_name,还有用户简介通常会储存的其他几个属性。在类User定义一个名为describe_user()的方法,它打印用户信息的摘要;再定义一个名为greet_user()的方法,它向用户发出个性化的问候。
创建多个表示不同用户的实例,并对每个实例都调用上述两个方法。

class User():

	def __init__(self, first_name, last_name, age, career):
		self.f_name = first_name
		self.l_name = last_name
		self.age = age
		self.career = career

	def describe_user(self):
		print("\nThe user's name is " + self.f_name.title() + self.l_name.title() + ".")
		print("Age is " + str(self.age) + ".")
		print("The user's career is " + self.career.title() + ".")

	def greet_user(self):
		print("Hello," + self.f_name.title() + " " + self.l_name.title() + ".")

user_a = User('wang', 'xizhi', 25, 'calligrapher' )
user_b = User('Xie', 'an', 40, 'polician')
user_c = User('Xie', 'lingyun', 37, 'poet')

user_a.describe_user()
user_a.greet_user()

user_b.describe_user()
user_b.greet_user()

user_c.describe_user()
user_c.greet_user()

build


The user's name is WangXizhi.
Age is 25.
The user's career is Calligrapher.
Hello,Wang Xizhi.

The user's name is XieAn.
Age is 40.
The user's career is Polician.
Hello,Xie An.

The user's name is XieLingyun.
Age is 37.
The user's career is Poet.
Hello,Xie Lingyun.
[Finished in 0.1s]

9-4 就餐人数

(1)①

class Restaurant():
	"""docstring for Restaurant"""
	
	def __init__(self, restaurant_name, cuisine_type):
		self.name = restaurant_name
		self.type = cuisine_type
		self.number_served = 0 
		#设置该属性的默认值为0

	def count_number(self):
		print("There were " + str(self.number_served) + " customers having meals in the restaurant.")
		#打印有多少人在这个餐馆就餐过。


restaurant = Restaurant('mamala', 10)
restaurant.count_number() 

build

There were 0 customers having meals in the restaurant.
[Finished in 0.3s]


上述类主体不变,用句点表示法直接访问并设置属性number_served

restaurant = Restaurant('mamala', 10)
restaurant.number_served = 100
restaurant.count_number()

build

There were 100 customers having meals in the restaurant.

(2)(3)

class Restaurant():
	"""docstring for Restaurant"""
	
	def __init__(self, restaurant_name, cuisine_type):
		self.name = restaurant_name
		self.type = cuisine_type
		self.number_served = 0 
		#设置该属性的默认值为0

	def count_number(self):
		print("There were " + str(self.number_served) + " customers having meals in the restaurant.")
		#打印有多少人在这个餐馆就餐过。

	def set_number_served(self, number2):
		"""设置就餐人数的方法"""
		self.number_served = number2

	def increment_number_served(self, number3):
		"""将就餐人数递增"""
		self.number_served += number3

restaurant = Restaurant('mamala', 10)
restaurant.set_number_served(99) 
restaurant.count_number()

restaurant.increment_number_served(20)
restaurant.count_number()

build

There were 99 customers having meals in the restaurant.
There were 119 customers having meals in the restaurant.

9-5 尝试登录次数

class User():

	def __init__(self, first_name, last_name, age, career, login_attempts):
		self.f_name = first_name
		self.l_name = last_name
		self.age = age
		self.career = career
		self.login_attempts = login_attempts
    
    #--snip--
	def login_attempts_read(self):
		"""打印出loginattempts的读数"""
		print(str(self.login_attempts))

	def increment_login_attempts(self, value):
		self.login_attempts += value

	def reset_login_attempts(self):
		self.login_attempts = 0

user = User("wang", "xizhi", 25, "calligrapher", 2) #创建一个实例
user.login_attempts_read()

number = 0
while number <= 5:
	user.increment_login_attempts(5)
	number += 1
	#调用increment_login_attempts()方法6次。

user.login_attempts_read()

user.reset_login_attempts()
user.login_attempts_read()

9-6冰淇淋小店

冰淇淋小店是一种特殊的餐馆。编写一个名为IceCreamStand的类,让它继承你为完成练习9-1或练习9-4而编写的Restaurant类。这两个版本的Restaurant类都可以,挑选你更喜欢的那个即可。添加一个名为flavors的属性,用于存储一个由各种口味的冰淇淋组成的列表。编写一个显示这些冰淇淋的方法。创建一个IceCreamStand实例,并调用这个方法。

使用了9-4的Restaurant的类

class Restaurant():
	"""docstring for Restaurant"""
	
	def __init__(self, restaurant_name, cuisine_type):
		self.name = restaurant_name
		self.type = cuisine_type
		self.number_served = 0 
		#设置该属性的默认值为0
		self.flavors = ['chocolate', 'strawberry', 'milk', 'kiwifruit'] 
		#添加一个名为flavors的属性,用于存储一个由各种口味的冰淇淋组成的列表。

	--snip--#9-4中的代码
	
	def display_flavors(self):
	    """编写一个显示这些冰淇淋的方法"""
		message = "This IceCreamStand provides icecreams of different flavors of "
		
		num = 0
		while num < 3:
			message += self.flavors[num] + ","
			num += 1

		message += self.flavors[3] + "."
		print(message)

class IceCreamStand(Restaurant):
	"""编写一个冰淇淋小店的类。继承Restaurant。"""
	def __init__(self, restaurant_name, cuisine_type):
		"""初始化父类的属性"""
		super().__init__(restaurant_name,cuisine_type)

my_icecream = IceCreamStand('Dairy Queen', 10)
my_icecream.display_flavors()

Build

This IceCreamStand provides icecreams of different flavors of chocolate,strawberry,milk,kiwifruit.

还存在的问题
flavor的属性添加在父类中还是添加在子类中
方法编写在父类中还是主类中
觉得自己这样处理不是很好

9-7 管理员

管理员是一种特殊的用户。编写一个名为Admin的类,让它继承你为完成练习9-3或练习9-5而编写的User类。添加一个privileges的属性,用于存储一个由字符串(如"can add post"、 “can delete post”、 "can ban user"等)组成的列表。编写一个名为show_privileges()的方法,它显示管理员的权限。创建一个Admin实例,并调用这种方法。

class User():

	def __init__(self, first_name, last_name, age, career, login_attempts):
		self.f_name = first_name
		self.l_name = last_name
		self.age = age
		self.career = career
		self.login_attempts = login_attempts
    
	--snip--#Above借用9-3 User的语句。不影响下面的内容。

class Admin(User):

	def __init__(self, first_name, last_name, age, career, login_attempts):
		"""初始化父类的属性"""
		super().__init__(first_name, last_name, age, career, login_attempts)
		self.privileges = ["can add post", "can delete post", "can ban user"]
		#添加了一个新的属性

	def show_privileges(self):
		"""显示管理员的权限"""
		num = 0
		while num < 3:
			message = "Admin " + self.privileges[num] + "."
			num += 1
			print(message)

admin = Admin("wang", "xizhi", 25, "calligrapher", 2) #创建Admin的实例
admin.show_privileges() #调用方法

build

Admin can add post.
Admin can delete post.
Admin can ban user.

9-8 权限

编写一个名为Privileges的类,它只有一个属性——privileges,其中存储了练习9-7所说的字符串列表。将方法show_privileges()移到这个类中。在Admin类中,将一个Privileges实例用作其属性。创建一个Admin实例,并使用方法show_privileges()来显示其权限。

class User():

	def __init__(self, first_name, last_name, age, career, login_attempts):
		self.f_name = first_name
		self.l_name = last_name
		self.age = age
		self.career = career
		self.login_attempts = login_attempts
    
	--snip--
	
class Privileges():

	def __init__(self, privileges = ["can add post", "can delete post", "can ban user"]):
		self.privileges = privileges
		#添加属性

	def show_privileges(self):
		"""显示管理员的权限"""
		num = 0
		while num < 3:
			message = "Admin " + self.privileges[num] + "."
			num += 1
			print(message)

class Admin(User):

	def __init__(self, first_name, last_name, age, career, login_attempts):
		"""初始化父类的属性"""
		super().__init__(first_name, last_name, age, career, login_attempts)
		self.privilege = Privileges()
	

admin = Admin("wang", "xizhi", 25, "calligrapher", 2) #创建Admin的实例
admin.privilege.show_privileges() #调用方法

刚开始的时候出现了错误。
错误如下

##line50&47出现的问题
TypeError: __init__() missing 1 required positional argument: 'privileges'

原code为
没有将形参与属性privileges关联起来
正确的code为
变量是self.privileges,该变量(属性)关联到当前创建的实例。具体见p139,这点要好好理解。
变量是self.privileges,该变量(属性)关联到当前创建的实例。具体见p139,这点要好好理解。

build

Admin can add post.
Admin can delete post.
Admin can ban user.

9-9 电瓶升级

在本节最后一个electric_car.py版本中,给Battery类添加一个名为upgrade_battery()的方法。这个方法检查电瓶容量,如果它不是85,就将它设置为85。创建一辆电瓶容量为默认值的电动汽车,调用方法get_range(),然后对电瓶进行升级,并再次调用get_range()。你会看到这辆车的续航里程增加了。

class Car():
	"""一次模拟汽车的简单尝试"""

	def __init__(self, make, model, year):
		"""初始化描述汽车的属性"""
		self.make = make
		self.model = model
		self.year = year
		self.odometer_reading = 0
		#名为odomerter_reading的属性
		#在方法 __init__()内指定初始值,无需包含为它提供初始值的形参。

	def get_descriptive_name(self):
		"""返回整洁的描述性信息"""
		long_name = str(self.year) + ' ' + self.make + ' ' + self.model
		return long_name.title()
	
	--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.")

	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)

	def upgrade_battery(self):
		"""检查电瓶容量并设置"""
		if self.battery_size != 85:
			self.battery_size = 85 
			#注意这里赋值的对象
			#一定要区分self.battery_size和battery_size

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()
my_tesla.battery.upgrade_battery()
my_tesla.battery.get_range()

build

2016 Tesla Model S
This car has a 70-kwh battery.
This car can go approximately 270 miles on a full charge.

注意区分self.battery_size和battery_size

9-10 导入Restaurant类

将最新的Restaurant类存储在一个模块中。在另一个文件中,导入Restaurant类,创建一个Restaurant实例,并调用Restaurant的一个方法,以确认import语句正确无误。

创建模块 restaurant.py 将Restaurant类存储在该模块中。
import语句如下。from 文件(模块)名 import 类名

from restaurant import Restaurant

restaurant = Restaurant('mamala', 10)  
#创建Restaurant类实例。
restaurant.set_number_served(99) 
restaurant.count_number()

restaurant.increment_number_served(20)
restaurant.count_number()

【只要注意import语句无误即没有大问题】

9-11 导入Admin类(这题要注意一下)

以为完成练习9-8而做的工作为基础,将User、Privileges和Admin类存储在一个模块中,再创建一个文件,在其中创建一个Admin实例并对其调用方法show_privileges(),以确认一切都能正确地运行。

创建模块,存储User、Privileges和Admin类
创建Admin实例

from user import Admin
#导入Admin类

admin = Admin("wang", "xizhi", 25, "calligrapher", 2)
admin.privilege.show_privileges()

build

Admin can add post.
Admin can delete post.
Admin can ban user.

9-12 多个模块

将User类存储在一个模块中,并将Privileges和Admin类存储在另一个模块中。再创建一个文件,在其中创建一个Admin实例,并对其调用方法show_privileges(),以确认一切都依然能够正确地运行。

(1)模块1 users.py

class User():

	def __init__(self, first_name, last_name, age, career, login_attempts):
		self.f_name = first_name
		self.l_name = last_name
		self.age = age
		self.career = career
		self.login_attempts = login_attempts
    
	def describe_user(self):
		print("\nThe user's name is " + self.f_name.title() + self.l_name.title() + ".")
		print("Age is " + str(self.age) + ".")
		print("The user's career is " + self.career.title() + ".")

	def greet_user(self):
		print("Hello," + self.f_name.title() + " " + self.l_name.title() + ".")
	
	def login_attempts_read(self):
		"""打印出loginattempts的读数"""
		print(str(self.login_attempts))

	def increment_login_attempts(self, value):
		self.login_attempts += value

	def reset_login_attempts(self):
	    self.login_attempts = 0

(2)模块2 Admin_privileges.py
在该模块中先导入User类。因为Admin类是User的子类
若不导入,python会引发错误

class Privileges():
	--snip--

**from users import User 

class Admin(User):
	--snip--

(3)创建Admin实例,调用方法

from Admin_privileges import Admin

admin = Admin("wang", "xizhi", 25, "calligrapher", 2) #创建Admin的实例
admin.privilege.show_privileges()

输出不再赘述。

9-13 使用OrderedDict

在练习6-4中,你使用了一个标准字典来表示词汇表。请使用OrderedDict类来重写这个程序,并确认输出的顺序与你在字典中添加的键-值对的顺序一致。

9-14 骰子

模块random包含以各种方式生成随机数的函数,其中的randint()返回一个位于指定范围内的整数。例如,下面的代码返回一个1~6内的整数:

from random import randint
x = randint(1,6)

请创建一个Die类,它包含一个名为sides的属性,该属性的默认值为6。编写一个名为roll_die()的方法,它打印位于1和骰子面数之间的随机数。创建一个6面的骰子,再掷10次。
创建一个10面的骰子和一个20面的骰子,并将它们都掷10次。

这题想得好痛苦,但出错还是因为对self.sides和sides的区分出问题

(1)按照要求:
①6面

from random import randint
"""从random模块中导入randint类"""

class Die():

	def __init__(self, sides=6):
		self.sides = sides

	def roll_die(self):
		x = randint(1, self.sides)
		print(str(x))

die = Die()

times = 1
while times <= 10:
	times += 1
	die.roll_die()

build

#生成10个1~6的随机数
6
2
5
6
3
3
2
1
4
1

②10面

from random import randint
--snip--
die = Die(10)

times = 1
while times <= 10:
	times += 1
	die.roll_die()

build

#生成1~10的随机数
8
5
6
1
5
10
10
9
6
8

③20面

from random import randint
--snip--

die = Die(20)

times = 1
while times <= 10:
	times += 1
	die.roll_die()

build

#生成1~20的随机数
16
16
13
1
4
14
4
11
13
10

(2)思考:如何能避免重写while循环语句。

from random import randint
"""从random模块中导入randint类"""

class Die():

	def __init__(self, sides=6, times=10):
		self.sides = sides
		self.times = times

	def roll_die(self):
		num = 1
		while num <= self.times:
			num += 1
			x = randint(1, self.sides)
			print(str(x))

die = Die(10,10)
die.roll_die()

将设定的投掷次数加入roll_die()方法,在方法内循环。最后调用方法即可。

9-15 Python Module of the Week

了解Python标准库.

总结

  • 关于markdown目录:[TOC]即可生成。要在行第一格输入。
  • 类编码风格要加以注意。在写习题时没有看到,没有注意。具体为
  • ①类名驼峰命名法
  • ②实例名和模块名都采用小写格式,并在单词之间加上下划线
  • ③每个类紧跟类定义包含一个文档字符串;模块也应该包含一个文档字符串
  • ④在类中,用一个空行分隔方法;在模块中,用两个空行来分隔类。
  • ⑤同时导入标准库中的模块和自己编写的模块时,先导入标准库模块的import语句,添加一个空行,再添加自己编写的模块的import语句。

猜你喜欢

转载自blog.csdn.net/weixin_43797280/article/details/84778481
今日推荐