一、對象的定義
對象是有屬性和方法組成的,在實際環境中也就是對象本身的變量和函數!比如一條魚,眼睛和尾巴就是屬性,會游泳就是他的技能!
基礎類的聲明:
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("有一條魚兒被吃掉了...")