前言
我們在了解面向對象的入門知識,知道如何定義一個類和對象的時候,我們應該向它更深的知識進行拓展。
@property 裝飾器
它的功能就是將一個隱喻的屬性進行包裝,該屬性是設計者不希望使用者直接訪問該屬性,這個時候就使用裝飾器@property。例如:
class Person(object):
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
# getter - 訪問器
@property
def age(self):
return self._age
# setter - 修改器
@age.setter
def age(self, age):
self._age = age if 20 < age < 60 else 30
def watch_av(self):
if self._age >= 18:
print('看片')
else:
print('看動漫')
slots魔法
slots可以限定當前的類中的屬性的個數(shù),需要注意的是它只能限定該類的對象并不能限定其子類。例如:
class Student(object):
# __slots__魔法的使用
__slots__ = ('_name', '_age')
def __init__(self, name, age):
self._name = name
self._age = age
@property # 屬性訪問器
def age(self):
return self._age
@age.setter # 屬性修改器
def age(self, age):
self._age = age if 15 < age < 25 else 20
def watch_av(self):
if self._age >= 18:
print('看片')
else:
print('看動漫')
靜態(tài)方法和類方法
所謂的靜態(tài)方法就是一個方法是屬于那一個類而不屬于該對象,關鍵字@staticmethod
,類方法就是對象所擁有的某些行為。
class Tr(object):
def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c
@property
def a(self):
return self._a
@property
def b(self):
return self._b
@property
def c(self):
return self._c
# 判斷是不是三角形
@staticmethod
def is_tr(a, b, c):
return a + b > c and a + c > b and b + c > a
def perimer(self):
return self._a + self._b + self._c
def main():
a = 10
b = 10
c = 12
if Tr.is_tr(a, b, c):
tr = Tr(a, b, c)
print('周長是:%d' % tr.perimer())
if __name__ == '__main__':
main()
和在類中定義靜態(tài)的方法一樣,我們也可以在類中定義類關鍵字@classmethon
例如:
沒有在類中定義類的時候:
import time
class Rectangle:
def __init__(self, width, height):
self._width = width
self._height = height
def perimeter(self):
return (self._width + self._height) * 2
def area(self):
return self._height * self._width
class Clock(object):
local_time = time.localtime()
get_time = list(local_time)
def __init__(self, hour=get_time[3], minute=get_time[4], second=get_time[5]):
# 不要參數(shù) 使用系統(tǒng)時間 python中的time模塊
self._hour = hour
self._minute = minute
self._second = second
def run(self):
self._second += 1
if self._second == 60:
self._minute += 1
self._second = 0
if self._minute == 60:
self._minute =0
self._hour += 1
if self._hour == 24:
self._hour =0
def show(self):
return '%02d:%02d:%02d' % (self._hour, self._minute, self._second)
# 下面的方法可以獲得對象的字符串表示形式
# 當我們用print打印對象時候會自動調用該方法
# def __str__(self):
# return '%02d:%02d:%02d' % (self._hour, self._minute, self._second)
def main():
clock = Clock()
while True:
print(clock.show())
clock.run()
time.sleep(1)
if __name__ == '__main__':
main()
使用了之后:
from time import time, localtime, sleep
class Clock(object):
"""數(shù)字時鐘"""
def __init__(self, hour=0, minute=0, second=0):
self._hour = hour
self._minute = minute
self._second = second
@classmethod
def now(cls):
ctime = localtime(time())
return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)
def run(self):
"""走字"""
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0
def show(self):
"""顯示時間"""
return '%02d:%02d:%02d' % \
(self._hour, self._minute, self._second)
def main():
# 通過類方法創(chuàng)建對象并獲取系統(tǒng)時間
clock = Clock.now()
while True:
print(clock.show())
sleep(1)
clock.run()
if __name__ == '__main__':
main()
類之間的關系有如下:
類和類之間的關系有三種:is-a, has-a, use-a
is-a : 簡單說就是一個繼承關系,比如學生和人類,老鼠和動物。
has-a : 是一種強關聯(lián)的關系,比如汽車和輪子,4
use-a :是一種依賴關系,比如人撞墻,人使用了墻,否則無墻可撞。
20180313194509293.png
繼承和多態(tài)
何為繼承,就是一個類從另外的一個類中得到該類的屬性和方法就稱之為繼承。得到屬性和方法的就叫做子類,提供屬性和方法的就叫做父類。子類之中除了父類之中的那些東西之外還可以添加自己需要的方法和屬性。當子類繼承父類的方法的時候可以重新修改該方法,這就稱之為多態(tài)
繼承:
# 繼承-- 從已經有的類創(chuàng)建新類的過程
# 提供繼承信息的稱為父類(超類/基類)
# 得到繼承信息的稱為子類(派生類/衍生類)
# 通過繼承我們可以將子類中的重復代碼抽取到父類中
# 子類通過繼承并復用這些代碼來減少重復代碼的編寫
# 將來如果要維護子類的公共代碼只需要在父類中進行操作即可
# has - a 關聯(lián)關系 (人和手)
# use - a 依賴關系 (人和房子)
# is - a 繼承關系 (老師和人類,學生和人類)
# 任何時候子類可以替換掉父類
class Person(object):
"""人"""
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age
def play(self):
print('%s正在愉快的玩耍.' % self._name)
def watch_av(self):
if self._age >= 18:
print('%s正在觀看愛情動作片.' % self._name)
else:
print('%s只能觀看《熊出沒》.' % self._name)
class Student(Person):
"""學生"""
def __init__(self, name, age, grade):
super().__init__(name, age)
self._grade = grade
@property
def grade(self):
return self._grade
@grade.setter
def grade(self, grade):
self._grade = grade
def study(self, course):
print('%s的%s正在學習%s.' % (self._grade, self._name, course))
class Teacher(Person):
"""老師"""
def __init__(self, name, age, title):
super().__init__(name, age)
self._title = title
@property
def title(self):
return self._title
@title.setter
def title(self, title):
self._title = title
def teach(self, course):
print('%s%s正在講%s.' % (self._name, self._title, course))
def main():
stu = Student('王大錘', 15, '初三')
stu.study('數(shù)學')
stu.watch_av()
t = Teacher('mr.l', 26, '博士')
t.teach('人體學')
t.watch_av()
if __name__ == '__main__':
main()
多態(tài):
from abc import ABCMeta, abstractmethod
class Pet(object, metaclass=ABCMeta):
"""寵物"""
def __init__(self, nickname):
self._nickname = nickname
@abstractmethod
def make_voice(self):
"""發(fā)出聲音"""
pass
class Dog(Pet):
"""狗"""
def make_voice(self):
print('%s: 汪汪汪...' % self._nickname)
class Cat(Pet):
"""貓"""
def make_voice(self):
print('%s: 喵...喵...' % self._nickname)
def main():
pets = [Dog('旺財'), Cat('凱蒂'), Dog('大黃')]
for pet in pets:
pet.make_voice()
if __name__ == '__main__':
main()
上面代碼中的Pet
是一個抽象類,不能直接使用它來創(chuàng)建一個對象,但是可以使用子類來繼承它,在子類繼承它的時候必須繼承該抽象類的抽象方法,
綜合案例
1 奧特曼打小怪獸
from random import randint
class Ultraman(object):
__slots__ = ('_name', '_hp', '_mp') # 限定當前這個類里面只有這三個字段
def __init__(self, name, hp, mp):
self._name = name
self._hp = hp
self._mp = mp
@property
def name(self):
return self._name
@property
def hp(self):
return self._hp
@hp.setter
def hp(self, hp):
self._hp = hp if hp > 0 else 0
@property
def mp(self):
return self._mp
@mp.setter
def mp(self, mp):
self._mp = mp if mp >= 0 else 0
def attack(self, monster):
injury = randint(15, 25)
monster.hp -= injury
def huge_attack(self, monster):
if self._mp >= 50:
self._mp -= 50
injury = monster.hp * 3 // 4
injury = injury if injury >= 50 else 50
monster.hp -= injury
else:
self.attack(monster)
def magic_attack(self, monsters):
if self.mp >= 20:
self.mp -= 20
for monster in monsters:
monster.hp -= randint(10, 15)
def __str__(self):
return '%s奧特曼\n' % self._name + \
'生命值: %d\n' % self._hp + \
'魔法值: %d\n' % self._mp
class Monster(object):
__slots__ = ('_name', '_hp')
def __init__(self, name, hp):
self._name = name
self._hp = hp
@property
def name(self):
return self._name
@property
def hp(self):
return self._hp
@hp.setter
def hp(self, hp):
self._hp = hp if hp >=0 else 0
def attack(self, ultraman):
injury = randint(10, 20)
ultraman.hp -= injury
def __str__(self):
return '%s怪獸\n' % self.name + \
'生命值: %d\n' % self.hp
def main():
u = Ultraman('駱昊', 1000, 500)
print(u)
m1 = Monster('舒玲1', 250)
m2 = Monster('舒玲2', 250)
m3 = Monster('舒玲3', 250)
ms = [m1, m2, m3]
for val in ms:
print(val, end=' ')
attack_round = 1
while u.hp > 0 and (m1.hp + m2.hp + m3.hp) > 0:
print('====第%d回合====' % attack_round)
a = randint(1, 10)
b = randint(0, 2)
if a <= 6:
while ms[b].hp <= 0:
b = randint(0, 2)
u.attack(ms[b])
elif 6 < a <= 9:
u.magic_attack(ms)
else:
u.huge_attack(ms[b])
for index in range(len(ms)):
if ms[index].hp > 0:
ms[index].attack(u)
print(u)
for val in ms:
print(val, end=' ')
attack_round += 1
if u.hp > 0:
print('%s奧 特曼勝利' % u.name)
else:
print('小怪獸獲勝')
if __name__ == '__main__':
main()
2 Puke
from random import randrange
class Card(object):
"""一張牌"""
def __init__(self, suite, face):
self._suite = suite
self._face = face
@property
def face(self):
return self._face
@property
def suite(self):
return self._suite
def __str__(self):
if self._face == 1:
face_str = 'A'
elif self._face == 11:
face_str = 'J'
elif self._face == 12:
face_str = 'Q'
elif self._face == 13:
face_str = 'K'
else:
face_str = str(self._face)
return '%s%s' % (self._suite, face_str)
class Poker(object):
"""一副牌"""
def __init__(self):
self._cards = []
self._current = 0
for suite in '????':
for face in range(1, 14):
card = Card(suite, face)
self._cards.append(card)
@property
def cards(self):
return self._cards
def shuffle(self):
"""洗牌"""
self._current = 0
cards_len = len(self._cards)
for index in range(cards_len):
pos = randrange(cards_len)
self._cards[index], self.cards[pos] = \
self._cards[pos], self.cards[index]
# 使用屬性一般需要返回一個值
@property
def next(self):
"""發(fā)牌"""
card = self.cards[self._current]
self._current += 1
return card
@property
def has_next(self):
"""還有沒有牌"""
return self._current < len(self._cards)
class Player(object):
def __init__(self, name):
self._name = name
self._cards_on_hand = []
@property
def name(self):
return self._name
@property
def cards_on_hand(self):
return self._cards_on_hand
# 得到卡片
def get(self, card):
self._cards_on_hand.append(card)
# 排序
def arrange(self):
self._cards_on_hand.sort(key=get_key)
# 點數(shù)計數(shù)
@property
def count(self):
total = 0
for val in self._cards_on_hand:
total += val.face
return total
def get_key(card):
return card.face
def main():
p = Poker()
p.shuffle()
user = Player('ljl')
com1 = Player('c1')
while p.has_next:
print()
print('玩家:%d-------電腦:%d' % (user.count, com1.count))
if user.count > 0:
for i in user.cards_on_hand:
print(i, end='')
print('-------------', end='')
for i in com1.cards_on_hand:
print(i, end='')
f = input('是否還要繼續(xù)游戲y or n:')
if f == 'y':
user.get(p.next)
if user.count > 21:
print('%d玩家輸了' % user.count)
return False
if com1.count < 15:
com1.get(p.next)
if com1.count > 21:
print('玩家勝利')
return False
if __name__ == '__main__':
main()