"魔法"方法
1. 打印id()
如果把BMW使用print进行输出的话,会看到如下的信息
即看到的是创建出来的BMW对象在内存中的地址
2. 定义__str__()方法
classCar:
def__init__(self, newWheelNum, newColor):
self.wheelNum = newWheelNum
self.color = newColor
def__str__(self):
msg ="嘿。。。我的颜色是"+ self.color +"我有"+str(self.wheelNum) +"个轮胎..."
returnmsg
defmove(self):
print('车在跑,目标:夏威夷')
BMW = Car(4,"白色")
print(BMW)
总结
在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法
当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据
self
1. 理解self
看如下示例:
# 定义一个类
classAnimal:
# 方法
def__init__(self, name):
self.name = name
defprintName(self):
print('名字为:%s'%self.name)
# 定义一个函数
defmyPrint(animal):
animal.printName()
dog1 = Animal('西西')
myPrint(dog1)
dog2 = Animal('北北')
myPrint(dog2)
运行结果:
总结
所谓的self,可以理解为自己
可以把self当做C++中类里面的this指针一样理解,就是对象自身的意思
某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可
应用:烤地瓜
为了更好的理解面向对象编程,下面以“烤地瓜”为案例,进行分析
1. 分析“烤地瓜”的属性和方法
示例属性如下:
cookedLevel : 这是数字;0~3表示还是生的,超过3表示半生不熟,超过5表示已经烤好了,超过8表示已经烤成木炭了!我们的地瓜开始时时生的
cookedString : 这是字符串;描述地瓜的生熟程度
condiments : 这是地瓜的配料列表,比如番茄酱、芥末酱等
示例方法如下:
cook(): 把地瓜烤一段时间
addCondiments(): 给地瓜添加配料
__init__(): 设置默认的属性
__str__(): 让print的结果看起来更好一些
2. 定义类,并且定义__init__()方法
#定义`地瓜`类classSweetPotato:
'这是烤地瓜的类'
#定义初始化方法
def__init__(self):
self.cookedLevel =
self.cookedString ="生的"
self.condiments = []
3. 添加"烤地瓜"方法
#烤地瓜方法
defcook(self, time):
self.cookedLevel += time
ifself.cookedLevel >8:
self.cookedString ="烤成灰了"
elifself.cookedLevel >5:
self.cookedString ="烤好了"
elifself.cookedLevel >3:
self.cookedString ="半生不熟"
else:
self.cookedString ="生的"
4. 基本的功能已经有了一部分,赶紧测试一下
把上面2块代码合并为一个程序后,在代码的下面添加以下代码进行测试
mySweetPotato = SweetPotato()
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
print(mySweetPotato.condiments)
完整的代码为:
classSweetPotato:
'这是烤地瓜的类'
#定义初始化方法
def__init__(self):
self.cookedLevel =
self.cookedString ="生的"
self.condiments = []
#烤地瓜方法
defcook(self, time):
self.cookedLevel += time
ifself.cookedLevel >8:
self.cookedString ="烤成灰了"
elifself.cookedLevel >5:
self.cookedString ="烤好了"
elifself.cookedLevel >3:
self.cookedString ="半生不熟"
else:
self.cookedString ="生的"
# 用来进行测试
mySweetPotato = SweetPotato()
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
print(mySweetPotato.condiments)
5. 测试cook方法是否好用
在上面的代码最后面添加如下代码:
print("------接下来要进行烤地瓜了-----")
mySweetPotato.cook(4)#烤4分钟
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
6. 定义addCondiments()方法和__str__()方法
def__str__(self):
msg = self.cookedString +" 地瓜"
iflen(self.condiments) >:
msg = msg +"("
fortempinself.condiments:
msg = msg + temp +", "
msg = msg.strip(", ")
msg = msg +")"
returnmsg
defaddCondiments(self, condiments):
self.condiments.append(condiments)
7. 再次测试
完整的代码如下:
classSweetPotato:
"这是烤地瓜的类"
#定义初始化方法
def__init__(self):
self.cookedLevel =
self.cookedString ="生的"
self.condiments = []
#定制print时的显示内容
def__str__(self):
msg = self.cookedString +" 地瓜"
iflen(self.condiments) >:
msg = msg +"("
fortempinself.condiments:
msg = msg + temp +", "
msg = msg.strip(", ")
msg = msg +")"
returnmsg
#烤地瓜方法
defcook(self, time):
self.cookedLevel += time
ifself.cookedLevel >8:
self.cookedString ="烤成灰了"
elifself.cookedLevel >5:
self.cookedString ="烤好了"
elifself.cookedLevel >3:
self.cookedString ="半生不熟"
else:
self.cookedString ="生的"
#添加配料
defaddCondiments(self, condiments):
self.condiments.append(condiments)
# 用来进行测试
mySweetPotato = SweetPotato()
print("------有了一个地瓜,还没有烤-----")
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
print(mySweetPotato.condiments)
print("------接下来要进行烤地瓜了-----")
print("------地瓜经烤了4分钟-----")
mySweetPotato.cook(4)#烤4分钟
print(mySweetPotato)
print("------地瓜又经烤了3分钟-----")
mySweetPotato.cook(3)#又烤了3分钟
print(mySweetPotato)
print("------接下来要添加配料-番茄酱------")
mySweetPotato.addCondiments("番茄酱")
print(mySweetPotato)
print("------地瓜又经烤了5分钟-----")
mySweetPotato.cook(5)#又烤了5分钟
print(mySweetPotato)
print("------接下来要添加配料-芥末酱------")
mySweetPotato.addCondiments("芥末酱")
print(mySweetPotato)
隐藏数据
可能你已经意识到,查看过着修改对象的属性(数据),有2种方法
1. 直接通过对象名修改
SweetPotato.cookedLevel =5
2. 通过方法间接修改
SweetPotato.cook(5)
分析
明明可以使用第1种方法直接修改,为什么还要定义方法来间接修改呢?
至少有2个原因:
如果直接修改属性,烤地瓜至少需要修改2部分,即修改cookedLevel和cookedString。而使用方法来修改时,只需要调用一次即可完成
如果直接访问属性,可能会出现一些数据设置错误的情况产生例如cookedLevel = -3。这会使地瓜比以前还生,当然了这也没有任何意义,通过使用方法来进行修改,就可以在方法中进行数据合法性的检查
应用:存放家具
#定义一个home类classHome:
def__init__(self, area):
self.area = area#房间剩余的可用面积
#self.light = 'on' #灯默认是亮的
self.containsItem = []
def__str__(self):
msg ="当前房间可用面积为:"+ str(self.area)
iflen(self.containsItem) >:
msg = msg +" 容纳的物品有: "
fortempinself.containsItem:
msg = msg + temp.getName() +", "
msg = msg.strip(", ")
returnmsg
#容纳物品
defaccommodateItem(self,item):
#如果可用面积大于物品的占用面积
needArea = item.getUsedArea()
ifself.area > needArea:
self.containsItem.append(item)
self.area -= needArea
print("ok:已经存放到房间中")
else:
print("err:房间可用面积为:%d,但是当前要存放的物品需要的面积为%d"%(self.area, needArea))
#定义bed类classBed:
def__init__(self,area,name ='床'):
self.name = name
self.area = area
def__str__(self):
msg ='床的面积为:'+ str(self.area)
returnmsg
#获取床的占用面积
defgetUsedArea(self):
returnself.area
defgetName(self):
returnself.name
#创建一个新家对象
newHome = Home(100)#100平米
print(newHome)
#创建一个床对象
newBed = Bed(20)
print(newBed)
#把床安放到家里
newHome.accommodateItem(newBed)
print(newHome)
#创建一个床对象
newBed2 = Bed(30,'席梦思')
print(newBed2)
#把床安放到家里
newHome.accommodateItem(newBed2)
print(newHome)
总结:
如果一个对象与另外一个对象有一定的关系,那么一个对象可用是另外一个对象的属性
思维升华:
添加“开、关”灯,让房间、床一起亮、灭
领取专属 10元无门槛券
私享最新 技术干货