开发者学堂课程【Python入门 2020年版:面向对象练习】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/639/detail/10374
面向对象练习
内容介绍:
一、面向对象练习
二、如何写代码来放进去家具?
一、面向对象练习
#房子(House)有户型、总面积、剩余面积和家具名称列表属性,#新房子没有任何的家具
#将家具的名称追加到家具名称列表中
#判断家具的面积是否超过剩余面积,如果超过,提示不能添加这件家具
#家具(Furniture)有名字和占地面积属性,其中
#席梦思(bed)占地4平米,
#衣柜(chest)占地2平米
#餐桌(table)占地1.5平米,
#将以上三件家具添加到房子中
#打印房子时,要求输出:户型、总面积、剩余面积、家具名称列表
class House(object):
def __init__(self,house_type,total_area,free_area,fru_list):
self.house_type = house_type
self.total_area = total_area
self.free_area = free_area
self.fru_list = fru_list
house1 = House(‘两室一厅‘,56)
应从需要来看,该先定义房子,之后创建一个对象并添加对象内容。在写 house 的时候会调用__init__方法,这个方法也就是函数,再写函数的时候有一些参数是必须要存的,不用存的参数是有默认值的。
之前讲的缺省参数,就是不给对应属性应有的值,如果不给,直接运行就会报错,如果要有默认值就要把原来的
def
__init__(self,house_type,total_area,free_area,fru_list):
语句修改为
def __init__(self,house_type,total_area,free_area,fru_list = []):
这个时候可能会报错,它会提示默认值最好不要采用可变的类型。
最好的方式是写为
def
__init__(self,house_type,total_area,free_area,fru_list = None):
并加入判断语句
if fru_list is None:
fru_list = []
如果这个值是 None,就会将 fru_list 设置为空列表。这个if语句是把光标防在 fru_list 上面,就会有智能修改的点击项,点击后会自动生成if的判断语句。
在创建房间对象的时候,传入户型和总面积,而剩余面积是不能传的。比如在传入户型的值为56,剩余面积值为120。这个就是有问题的,就需要在原来的语句 def
__init__(self,house_type,total_area,free_area,fru_list = None):删掉 free_area。但下面的 self.free_area = free_area语句就会报错,因为它具备free_area的属性但没有它的值。
代码目前内容为:
def __init__(self,house_type,total_area,free_area,fru_list = None):
if fru_list is None:
fru_list = []
self.house_type = house_type
self.total_area = total_area
self.free_area = free_area
self.fru_list = fru_list
house1 = House(‘两室一厅‘,56)
这段内容中还涉及到了内存,在内存中只要一申请创建对象就会创建对应的内存空间。
house1和 self 都指向了同一块内存空间,现在写了有一个 self.house_type 等于传回来的两室一厅,def __init__语句中的 house_type 是等于语句 self.house_type = house.type 中的第二个 house_type。
而 def __init__语句中的 house_type 是通过新创对象的‘两室一厅‘传过去的。还有 total_area,内存中的这个变量对应的值是self.total_area = total_area中的第二个 total_area,而这个 total_area 对应的是 def __init__语句中的total_area 它的值为56。还有一个内存属性是 free_area 等于的值是 free_area,但在 def __init__中没有这个参数,此时会报错。
在这做一个规定,剩余面积是总面积的60%,所以它的语句 self.free_area = free_area 应该改为 self.free_area = total_area * 0.6。因为剩余面积与总面积是有关系的,所以就需要加一个计算来得到剩余面积。最后一个 fru_list 等于的是 def __init__中的fru_list,如果它是空的话,它对应的就是一个空列表。
self.house_type = house_type 这俩个 house_type 不是同一个意思,这个在之前的面向对象课程中讲到过。
def __init__中的 house_type 是指的下面的变量传的参数,把里面的值传给 house_type,这里面有一个操作是house_type = ‘两室一厅’,total_area = 56,把函数的参数赋值给属性。
房子的属性就完成了,除了属性,还具有一些行为,要将家具的名称追加到家具名称列表中,就需要加入以下语句:
def add_fru(self):
print(‘需要将家具添加到房子里’)
并创建一个家具类,在逐步创建对象
class Furniture(object)
def __init__(self,name,area):
self.name = name
self.area = area
bed = Furniture(
‘席梦思’,4)
chest = Furniture(
‘衣柜’,2)
table = Furniture(‘餐桌’,1.5)
把家具添加到房间里,面向对象的关注点在于让谁做。把家具添加到房间里,可以让家具做,加入 def add_to_house(self):。根据设计,主要是看到底是加给房间好还是家具好,在这个里面分析下来是交给房子好。因为房子中说到,如果房子面积超过剩余面积,就不会让加了,因为房子会清楚自己的剩余面积,所以交给房子更好一点。
在房子里面有一个 add_fru 方法,这个活在开发的时候是很灵活的。一件事到底交给是来做,把逻辑理清楚就可以。
这个让房子来做,让房子来添加家具。也可以是家具来做,把家具添加到房子里面。按现在的需求,把这个事交给房子更好。
因为有要求当房子的面积大于总面积时不能再加入家具,房子能够拿到自己的剩余面积,所以选择让房子来做这件事更急方便一点。
用 house 来做,就调用 add_fru 方法。添加 house.add_fru(bed)直接运行就会报错,报错的原因时 fru 中不需要参数。
之前讲过 self 也是一个参数,但不需要管。需要再加入一个参数,语句变为
def add_fru(self
,x):
print
(‘需要将家具添加到房子里’)
整理代码:
class House(object):
def __init__(self,house_type,total_area,free_area,fru_list = None):
if fru_list is None:
fru_list = []
self.house_type = house_type
self.total_area = total_area
self.free_area = free_area
self.fru_list = fru_list
def add_fru(self
,x):
print(‘需要将家具添加到房子里’)
class Furniture(object)
def __init__(self,name,area):
self.name = name
self.area = area
house1 = House(
‘两室一厅‘,56)
bed = Furniture(
‘席梦思’,4)
chest = Furniture(
‘衣柜’,2)
table = Furniture(
‘餐桌’,1.5)
house.add_fru(bed)
运行后的结果为:
这就是房子的家具添加方法,把这个活交给房子来做。
注意:
这个工作它不一定给房子,它也可以给家具。讲了两种,一个是房子加家具,还有一个是家具放到房子中。
交给房子之后,写了一个 add_fru(self,x)。这个里面的x,一些会把 house add_fru(bed)中的 bed 传给 x 的操作,x = bed
刚开始学习面向对象,会有很多的疑惑是正常的。刚刚讲过的代码中是由四个对象的,这四个对象都有自己的内存空间。
加入语句打印出 house 的内存地址 print(‘0x%X 0x%X 0x%X 0x%X’ %(id(house),id(bed),id(chest),id(table)))
打印结果如下:
每一个对应的地址为0x223cbbbf0c8 、0x223CBBBF108、0x223CBBBF148、0x223CBBBF188
对象就是内存的一块空间,house 的这个房间中存的是 house_type:两室一厅;total_area:56;free_area:33.6;fru_list:[ ] 。
bed 这个房间中存的是 name:席梦思;area:4。chest 这个房间中存的是 name:衣柜;area:2。
bed 这个房间中存的是 name:餐桌;area:1.5。
House.add_fru(bed),面向对象的思想就是 house 这个对象是由 House 类产生的,就可以用 House 这个类中所有的方法。这就是可以使用 add_fru(self,x)这个方法,之前还说过谁调用这个 self 谁就指的是这个 self。
现在是 house 调用的 house 对象的 add_fru 方法,所以这个 self 指的是 house。也就是.前面的内容代表的是所调用的对象,这个就是 self 调用的函数。之后,x 传给 bed,就是执行语句 x = bed,现在 x 指向的是 bed 内存空间。
这个题的逻辑是判断家具的面积是否超过剩余面积,如果超过,提示不能添加这件家具。先进行简单的,加入家具席梦思,把席梦思放到家具列表中。
二、如何写代码来放进去家具?
在 add_fru()函数中能访问到 house 的内存,因为 self 指的就是 house。
通过 self 找到内存空间,再找到 fru_list,最后再加入席梦思。注意要求是加入家具的名称,而不是把整个的家具放进去。还要获取家具的名字,在 add_fru()函数中能访问到席梦思,x就是席梦思。X.name 就是可以获取名字的方法,最后在加入到 fru_list 中就完成了。
注意不可以一上来就加,需要先进行判断。append 函数是对列表最佳元素的判断,如果可放进去了同时,还要减去成为剩余面积。到最后面积不够,就会提示放不进去。
这个 x 是个变量,是一个形参会不断指向一个值。加一个 x 就会指向一个新的,只要在调用 add_fru 方法,就会把逻辑再走一遍。
代码语句为:
if self.free_area < x.area:
print(
‘剩余面积不足,就放不进去了’)
else
:
self.fru_list.append(x.name)
self.free_area -= x.area
整理代码:
class House(object):
def __init__(self,house_type,total_area,free_area,fru_list = None):
if fru_list is None:
fru_list = []
self.house_type = house_type
self.total_area = total_area
self.free_area = free_area
self.fru_list = fru_list
def add_fru(self
,x):
print(‘需要将家具添加到房子里’)
class Furniture(object)
def __init__(self,name,area):
self.name = name
self.area = area
def add_fru(self,x)
if self.free_area < x.area:
print(‘剩余面积不足,就放不进去了’)
else
:
self.fru_list.append(x.name)
self.free_area -= x.area
house1 = House(
‘两室一厅‘,56)
bed = Furniture(
‘席梦思’,4)
chest = Furniture(
‘衣柜’,2)
table = Furniture(
‘餐桌’,1.5)
house.add_fru(bed)
house.add_fru(chest)
house.add_fru(table)
print(house)
运行结果为:
打印出的是内存地址。
最后在打印房子内容的时候要求有的信息,重写以一个 def __str__(self),要返回一个字符串,不能用print(‘hello’)。
当 print 打印一个对象的时候,会调用这个对象的__repr__或者__str__方法,获取它们的返回值。
加入语句;
def __str__(self):
return‘hello‘
整理代码:
class House(object):
def __init__(self,house_type,total_area,free_area,fru_list = None):
if fru_list is None:
fru_list = []
self.house_type = house_type
self.total_area = total_area
self.free_area = free_area
self.fru_list = fru_list
def add_fru(self
,x):
print(
‘需要将家具添加到房子里’)
def __str__(self):
return
‘hello‘
class Furniture(object)
def __init__(self,name,area):
self.name = name
self.area = area
def add_fru(self,x)
if self.free_area < x.area:
print(‘剩余面积不足,就放不进去了’)
else
:
self.fru_list.append(x.name)
self.free_area -= x.area
house1 = House(
‘两室一厅‘,56)
bed = Furniture(
‘席梦思’,4)
chest = Furniture(
‘衣柜’,2)
table = Furniture(
‘餐桌’,1.5)
house.add_fru(bed)
house.add_fru(chest)
house.add_fru(table)
print(house)
运行结果为:
不再打印内存地址,结果中就只有 hello。
同样的,把语句换为
def __str__(self):
return‘户型={},总面积={},剩余面积={},家具列表={}‘.format()
这个时候在打印 print(house)就相当于打印 print(house.__str__()),
这是 house 调用的__str__方法,就可以拿到 house 的各种信息 return ‘户型={},总面积={},剩余面积={},家具列表={}
format(self.house_type, self.total_area, self.free_area, self.fru_list)
整理代码:
class House(object):
def __init__(self,house_type,total_area,free_area,fru_list = None):
if fru_list is None:
fru_list = []
self.house_type = house_type
self.total_area = total_area
self.fru_list.append(x.name)
self.free_area -= x.area
house1 = House(
‘两室一厅‘,56)
bed = Furniture(
‘席梦思’,4)
chest = Furniture(
‘衣柜’,2)
table = Furniture(
‘餐桌’,1.5)
house.add_fru(bed)
house.add_fru(chest)
house.add_fru(table)
print(house.__str__())
运行结果为:
把房子面积进行缩小改为 house1 = House(‘一室一厅‘,20)
加入新对象 sofa = Furniture(‘沙发’,10)
整理代码:
class House(object):
def __init__(self,house_type,total_area,free_area,fru_list = None):
if fru_list is None:
fru_list = []
self.house_type = house_type
self.total_area = total_area
self.free_area = free_area
self.fru_list = fru_list
def add_fru(self
,x):
print(‘需要将家具添加到房子里’)
def __str__(self):
return
‘户型={},总面积={},剩余面积={},家具列表={}
format(self.house_type, self.total_area, self.free_area, self.fru_list)
class Furniture(object)
def __init__(self,name,area):
print(‘剩余面积不足,就放不进去了’)
else
:
self.fru_list.append(x.name)
self.free_area -= x.area
house1 = House(
‘一室一厅‘,20)
bed = Furniture(
‘席梦思’,4)
chest = Furniture(
‘衣柜’,2)
table = Furniture(
‘餐桌’,1.5)
sofa = Furniture(
‘沙发’,10)
house.add_fru(bed)
house.add_fru(chest)
house.add_fru(table)
print(house.__str__())
运行结果为:
加入沙发:house.add_fru(sofa)
运行后的代码为:
注意:
可用面积是总面积的60%。所以本次中就只能放入一个沙发和衣柜。
在开发的时候关键的难点在于某一个对象代表的是什么,参数如何让存储,理解有困难的可以借助画图的方式来明白。