Python 面向对象 object oriented , 一切都是对象
对象把函数和数据收集在一起
1 真实世界中的对象
属性 attribute 球的颜色、形状
动作 action 捡球、抛球
2 Python中的对象
属性 attribute: 对象的特征
ball.color
ball.size
ball.weight
显示: print ball.size
赋值: ball.color = ‘green’
赋值给常规的、不是对象的变量: myColor = ball.color
赋值给其他对象的属性: myBall.color = yourBall.color
方法 method: 对象的动作,能够对对象做的操作
ball.kick()
ball.throw()
ball.inflate()
3 对象=属性+方法
object.attribute
object.method()
4 创建对象
分两步:
1、定义属性和方法,只是个蓝图和描述—— 类,并没有真正创建一个对象
2、用类来建立一个真正的对象,这个对象称为这个类的一个实例instance
# encoding=utf-8
# 定义一个类,记得类名首字母大写!
# 属性并不属于类?它属于各个实例。因为每个实例可有不同的属性
class Ball:
# 定义一个方法,记得加self关键字
def bounce(self):
if self.direction == 'down':
self.direction = 'up'
# 创建一个类的实例instance
myBall = Ball()
# 设置一些属性
myBall.direction='down'
myBall.color='red'
myBall.size='small'
# 打印对象的属性
print ("I just create a ball.")
print ("My ball is %s " %myBall.color) # 写法
print ("My ball is", myBall.size) # 写法 ,后会自动加个空格!!!
print ("My ball's direction is", myBall.direction) # 写法
print ("Now I am going to bounce the ball.")
print () # 回车
# 调用bounce方法
myBall.bounce()
print ("My ball's direction is", myBall.direction)
结果:
I just create a ball.
My ball is red
My ball is small
My ball's direction is down
Now I am going to bounce the ball.
My ball's direction is up
5 初始化对象
创建球对象时,并没有在size、color或directions中填入任何内容,必须在创建对象之后填充
有一种方法可以在创建对象时设置属性,称为初始化对象
初始化 initializing: 开始时做好准备
__init__()
创建类定义时,可以定义一个特定的方法__init__()
只要创建这个类的一个新实例,就会运行这个方法,完成初始化。
向__init__()方法传递参数,创建实例时就会把属性设置为你希望的值
每个对象都内置一个__init__()方法,如果在类定义中没有自己加入,就会有一个内置方法接管,工作就是创建对象
# 定义一个类,记得类名首字母大写!
class Ball:
# 定义一个特定的方法__init__(),只要创建这个类的一个新实例,就会运行这个方法
def __init__(self,color,size,direction):
self.color=color
self.size=size
self.direction=direction
# 定义一个方法,记得加self关键字
def bounce(self):
if self.direction == 'down':
self.direction = 'up'
# 创建一个类的实例instance,并设置一些属性
myBall=Ball('red','small','down')
# 打印对象的属性
print ("I just create a bll.")
print ("My ball is %s " %myBall.color) # 用%s、%d
print ("My ball is", myBall.size) # 用,is后会自动加个空格!!!
print ("My ball's direction is "+myBall.direction) # 用+连接字符串,需要写空格!!
print ("Now I am going to bounce the ball.")
print () # 回车
# 调用bounce方法
myBall.bounce()
print ("My ball's direction is", myBall.direction)
结果:
I just create a bll.
My ball is red
My ball is small
My ball's direction is down
Now I am going to bounce the ball.
My ball's direction is up
问题:print (myBall) 会打印:<__main__.Ball object at 0x1079c8518>,内置__str__()方法,默认的打印输出
特殊方法 __xxx__() 创建类时Python自动包含的一些方法
__str__()方法,打印一个对象时具体显示什么内容,Python会默认为以下内容:
1、实例在哪里定义()
2、类名(Ball)
3、存储实例的内存位置
不过如果你希望print为对象显示其他内容,可以定义自己的__str__(),这会覆盖内置的__str__()方法。
self并没有实际意义,就是这个实例引用名
# 定义一个类,记得类名首字母大写!
class Ball:
def __init__(self,color,size,direction):
self.color=color
self.size=size
self.direction=direction
def __str__(self):
msg="Hi, I am a "+self.size+" "+self.color+" ball!” # 字符串拼接,需要空格!!
return msg
myBall = Ball('red','small','down')
print (myBall)
结果:
Hi, I am a small red ball!
self
一个类可以创建多个对象实例:
cBall=Ball(‘red’,’small’,’down')
bBall=Ball(‘black’,’small’,’down’)
调用其中一个实例的方法:
bBall.bounce()
方法必须知道是哪个实例调用了它,self参数会告诉方法哪个对象调用它,称为:实例引用(instance reference)
实例引用会自动传递给方法,不需要写参数,通过另一个内置方法实现
6、示例类
# encoding=utf-8
# 定义一个类,记得类名首字母大写!
class Hotdog:
# 定义一个方法,设置默认属性
def __init__(self):
# 定义为数字类型,热狗烤了多长时间,0~3表示还是生的,超过3表示半生不熟,超过5表示已经烤好,超过8表示已经烤成木炭了!开始时是生的
self.cooked_time=0
# 定义为字符串,描述热狗的生熟程度
self.cooked_status=“raw"
# 描述热狗的配料列表,比如:番茄酱、芥末酱等
self.condiments=[]
# 定义一个新的__str__()函数,打印用的
def __str__(self):
msg = "This is a hotdog "
if len(self.condiments) > 0: # 要加self,可以不加吗?
msg = msg + "with "
for i in self.condiments:
msg = msg + i + "," # msg是个str,不是list
# strip()函数,。。。
msg = msg.strip(", ")
return msg
# 烤热狗方法
def cook(self,time):
self.cooked_time+=time
if self.cooked_time > 8:
self.cooked_status = "Charcoal"
elif self.cooked_time > 5:
self.cooked_status = "Welldone"
elif self.cooked_time > 3:
self.cooked_status = "Medium"
else:
self.cooked_status = 'Raw'
# 加调料方法
def add_condiments(self,condiment):
self.condiments.append(condiment)
# 创建实例
myHotdog = Hotdog()
# 检查属性
print (myHotdog.cooked_time)
print (myHotdog.cooked_status)
print (myHotdog.condiments)
print ()
# 检查cook函数
print ("Now I am cooking the Hotdog: ")
myHotdog.cook(4)
print (myHotdog.cooked_time)
print (myHotdog.cooked_status)
print (myHotdog.condiments)
print ()
# 检查add_condiments函数
print ("Now I am adding condiments to the Hotdog: ")
myHotdog.add_condiments('garlic')
print (myHotdog.cooked_time)
print (myHotdog.cooked_status)
print (myHotdog.condiments)
print ()
结果:
0
raw
[]
Now I am cooking the Hotdog:
4
Medium
[]
Now I am adding condiments to the Hotdog:
4
Medium
['garlic']
加__str__()函数
# encoding=utf-8
# 定义一个类,记得类名首字母大写!
class Hotdog:
# 定义一个方法,设置默认属性
def __init__(self):
self.cooked_time=0
self.cooked_status="raw"
self.condiments=[]
# 定义一个新的__str__()函数,打印用的
def __str__(self):
msg = "This is a hotdog "
if len(self.condiments) > 0: # 要加self,可以不加吗?
msg = msg + "with "
for i in self.condiments:
msg = msg + i + "," # msg是个str,不是list
# strip()函数,。。。
msg = msg.strip(", ")
return msg
# 烤热狗方法
def cook(self,time):
self.cooked_time+=time
if self.cooked_time > 8:
self.cooked_status = "Charcoal"
elif self.cooked_time > 5:
self.cooked_status = "Welldone"
elif self.cooked_time > 3:
self.cooked_status = "Medium"
else:
self.cooked_status = 'Raw'
# 加调料方法
def add_condiments(self,condiment):
self.condiments.append(condiment)
# 创建实例
myHotdog = Hotdog()
# 检查属性
print (myHotdog) # 实例名
print ()
# 检查cook函数
print ("Now I am cooking the Hotdog: ")
myHotdog.cook(4)
print (myHotdog) # 实例名
print ()
# 检查add_condiments函数
print ("Now I am adding condiments to the Hotdog: ")
myHotdog.add_condiments('garlic')
print (myHotdog) # 实例名
print ()
结果:
This is a hotdog
Now I am cooking the Hotdog:
This is a hotdog
Now I am adding condiments to the Hotdog:
This is a hotdog with garlic
7、隐藏数据
查看或修改对象中的数据(属性)有两种方法:
- 直接访问:myDog.cooked_level=5
- 使用修改属性的方法: myDog.cook(5)
为什么不直接修改呢?
- 省时省力:直接访问属性,烤热狗至少需要两部分;利用方法: 只用一次就可以完成。
- 直接访问属性,就会有这样的结果:cooked_level=cooked_level-1,热狗比原来还生,要确保只会增加不会减少
限制对对象数据的访问,使得只能通过使用方法来获取和修改这些数据,就称为数据隐藏 data hiding
8、多态和继承
多态 polymorphism : 同一个方法,不同的行为
- 对于不同的类,可以有两个(或多个)同名的方法。应用到不同的类,有不同的行为
class Triangle:
def __init__(self,width,height):
self.width=width
self.height=height
def getArea(self):
area=self.width * self.height / 2.0
return area
class Square:
def __init__(self,size):
self.size=size
def getArea(self):
area=self.size**2
return area
#先实例化,才能调用其方法
myTriangle=Triangle(3,5)
print (myTriangle.getArea())
mySquare=Square(3)
print (mySquare.getArea())
继承:向父母学习
- 类可以从其他类继承属性和方法
- 从其他类继承属性或方法的类称为派生类(derived class)或子类(subclass)
- 创建一个类,Game_object,有name等属性,如:coin、apple、hat和pick()方法(把硬币加到玩家的物品集合中)
- Coin类从Game_object派生,要继承父类的属性和方法,自动有一个name属性和pickUp方法,还需要一个value属性和spend()方法
class Game_object:
def __init__(self,name):
self.name=name
def pickUp(self):
# put code here to add the object
# to the player's collection
# 子类继承。。
class Coin(Game_object):
def __init__(self,value):
GameObject.__init__(self,"coin")
self.value=value
def spend(self,buyer,seller):
# put code here to remove the coin
# from the buyer's money and
# add it to the seller's money
9、未雨绸缪
建立一个代码桩,使用pass关键字作为一个占位符,称为代码桩 code stub,详细如下:
# encoding =utf-8
class Game_object:
def __init__(self,name):
self.name=name
def pickUp(self):
pass
# put code here to add the object
# to the player's collection
# 子类继承。。
class Coin(Game_object):
def __init__(self,value):
GameObject.__init__(self,"coin")
self.value=value
def spend(self,buyer,seller):
pass
# put code here to remove the coin
# from the buyer's money and
# add it to the seller's money