一、对象的定义
对象是有属性和方法组成的,在实际环境中也就是对象本身的变量和函数!比如一条鱼,眼睛和尾巴就是属性,会游泳就是他的技能!
基础类的声明:
class Fish(object): eyes = 2 def get_eye(self): return self.eyes def set_eye(self, eye): self.eyes = eye
二、类的三大特性
(一)、封装
有些时候我们不希望把对象的属性公开,就可以把它设为私有,python并没有像其他语言对成员的权限控制系统,如private和protected,默认情况下,python的所有属性都是公有的,可以被访问到,要设成私有,则在前面加双下划线,如"__eye",在类外部调用的时候,早需要把他进行封装,一般是把该属性放在一个可以访问到的方法里,提供调用,如下:
class Fish(object):
__eyes = 2
def get_eye(self):
return self.__eyes
fish = Fish()
print(fish.get_eye())
fish = Fish() print(fish.get_eye())
(二)、继承
继承可以使子类拥有父类的属性和方法,并且可以重些这些方法,加强代码的复用性,python中子类可以有多个父类,但是不建议这样使用,一般会产生重复调用的问题,Super().方法名,可以调用父类的方法(不用传参,作用是调用父类的方法,传的是子类实例的值)
#!/usr/bin/env python3 # -*- coding:utf-8 -*- class Fish(object): def __init__(self): self.eye=2 self.wb=1 def swam(self): print("我会游泳") class GoldFish(Fish): def __init__(self): super().__init__() self.wb = 3 self.cc="hello" gold = GoldFish() print(gold.eye) print(gold.wb) print(gold.cc) gold.swam()
(三)多态
指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
class Ball: def setName(self, name): self.name = name def kick(self): print("我叫%s,该死的,谁踢我..." % self.name) a = Ball() a.setName('球A') # 第一个参数self告诉Python是a对象在调用方法,因为是隐藏的并且由Python自己传入,所以我们这里不需要写进来。 b = Ball() b.setName('球B') c = Ball() c.setName('土豆') # 这叫不按套路出牌 a.kick() b.kick() c.kick()
三、组合
当几个对象是水平方向的时候,就应该考虑用组合,当对象是纵向的时候用继承
组合就是用一个类把2个平级层次的对象放在一起
class Turtle: def __init__(self, x): self.num = x class Fish: def __init__(self, x): self.num = x class Pool: def __init__(self, x, y): self.turtle = Turtle(x) self.fish = Fish(y) def print_num(self): print("水池里总共有乌龟 %d 只,小鱼 %d 条!" % (self.turtle.num, self.fish.num))
self就是把实例本身的参数绑定,只有传了self,才能顺利进行调用对象数据,他是实例对象的标志!
四、构造方法和实例方法
构造方法:
在对象被实例话的时候运行,如果规则定了参数,实例化的时候就必须指定参数!否则报错
class Fish(object): def __init__(self): self.eye=2 self.wb=1
析构方法:只有在程序退出和对象没有任何引用的情况下才会销毁!
__del__(self)
import time class Fish(object): def __del__(self): print("我被销毁了") fish1 = Fish() a = fish1 b = fish1 del b del a del fish1 time.sleep(100)
五、综合练习
import random as r
legal_x = [0, 10]
legal_y = [0, 10]
class Turtle:
def __init__(self):
# 初始体力
self.power = 100
# 初始位置随机
self.x = r.randint(legal_x[0], legal_x[1])
self.y = r.randint(legal_y[0], legal_y[1])
def move(self):
# 随机计算方向并移动到新的位置(x, y)
new_x = self.x + r.choice([1, 2, -1, -2])
new_y = self.y + r.choice([1, 2, -1, -2])
# 检查移动后是否超出场景x轴边界
if new_x < legal_x[0]:
self.x = legal_x[0] - (new_x - legal_x[0])
elif new_x > legal_x[1]:
self.x = legal_x[1] - (new_x - legal_x[1])
else:
self.x = new_x
# 检查移动后是否超出场景y轴边界
if new_y < legal_y[0]:
self.y = legal_y[0] - (new_y - legal_y[0])
elif new_y > legal_y[1]:
self.y = legal_y[1] - (new_y - legal_y[1])
else:
self.y = new_y
# 体力消耗
self.power -= 1
# 返回移动后的新位置
return (self.x, self.y)
def eat(self):
self.power += 20
if self.power > 100:
self.power = 100
class Fish:
def __init__(self):
self.x = r.randint(legal_x[0], legal_x[1])
self.y = r.randint(legal_y[0], legal_y[1])
def move(self):
# 随机计算方向并移动到新的位置(x, y)
new_x = self.x + r.choice([1, -1])
new_y = self.y + r.choice([1, -1])
# 检查移动后是否超出场景x轴边界
if new_x < legal_x[0]:
self.x = legal_x[0] - (new_x - legal_x[0])
elif new_x > legal_x[1]:
self.x = legal_x[1] - (new_x - legal_x[1])
else:
self.x = new_x
# 检查移动后是否超出场景y轴边界
if new_y < legal_y[0]:
self.y = legal_y[0] - (new_y - legal_y[0])
elif new_y > legal_y[1]:
self.y = legal_y[1] - (new_y - legal_y[1])
else:
self.y = new_y
# 返回移动后的新位置
return (self.x, self.y)
turtle = Turtle()
fish = []
for i in range(10):
new_fish = Fish()
fish.append(new_fish)
while True:
if not len(fish):
print("鱼儿都吃完了,游戏结束!")
break
if not turtle.power:
print("乌龟体力耗尽,挂掉了!")
break
pos = turtle.move()
# 在迭代器中删除列表元素是非常危险的,经常会出现意想不到的问题,因为迭代器是直接引用列表的数据进行引用
# 这里我们把列表拷贝给迭代器,然后对原列表进行删除操作就不会有问题了^_^
for each_fish in fish[:]:
if each_fish.move() == pos:
# 鱼儿被吃掉了
turtle.eat()
fish.remove(each_fish)
print("有一条鱼儿被吃掉了...")