欢迎订阅公众号 数据分析那些事儿
继承定义
继承性是指,在某种情况下,一个类会有“子类”。子类比原本的类(称为父类)要更加具体化。例如,“狗”这个类可能会有它的子类“牧羊犬”和“吉娃娃犬”。在这种情况下,“莱丝”可能就是牧羊犬的一个实例。子类会继承父类的属性和行为,并且也可包含它们自己的。我们假设“狗”这个类有一个方法(行为)叫做“吠叫()”和一个属性叫做“毛皮颜色”。它的子类(前例中的牧羊犬和吉娃娃犬)会继承这些成员。
总而言之,就是在此前的基础上进行修改,从而定义一个新类的能力。
扑克牌类
以扑克牌为例,一副牌有52张牌,有4种花色(suit)和13个等级(rank)。 4种花色是黑桃(Spades),红心(Hearts),方块(Diamonds),梅花(Clubs),13个等级是A、2、3、4、5、6、7、8、9、10、J、Q、K。
定义一个扑克类,代表一张标准的扑克牌。
class Porker:
"""代表一张标准的扑克牌"""
def __init__(self, suit=0, rank=2):
self.suit = suit
self.rank = rank
类属性
为了以大家能够轻松看懂的方式来打印扑克牌对象,我们需要一个从整数值到对应的等级和花色的映射。一种直接的方法是使用字符串列表。我们把这些列表赋值到类属性。
#在Porker类内部
suit_names = ["Clubs", "Diamonds", "Hearts", "Spades"]
rank_names = [None, "Ace", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "Jack", "Queen", "King"]
def __str__(self):
return '%s of %s' % (Porker.rank_names[self.rank],
Porker.suit_names[self.suit])
suit_names 和 rank_names是定义在类内部但在方法之外,被称为类属性,因为他们是被关联到 Porker 类对象上的。 suit 和 rank被关联到了特定的实例,被称为实例属性。
创建打印扑克牌
>>> pk = Porker(3,13)
>>> print(pk)
King of Spades
>>>
查看一下Porker和pk的类型
>>> type(Porker)
<class 'type'>
>>> type(pk)
<class '__main__.Porker'>
类属性在内存空间中是如何组织的?下面我们用对象图简释一下
Porker是一个类,它的类型是type;pk是Porker的实例,它的类型是Porker。一副牌类
class Deck:
def __init__(self):
"""初始化52张牌"""
self.cards = []
for suit in range(4):
for rank in range(1, 14):
pkr = Porker(suit, rank)
self.cards.append(pkr)
def __str__(self):
res = []
for card in self.cards:
res.append(str(card))
return '\n'.join(res)
def add_card(self, card):
self.cards.append(card)
def pop_card(self, i=-1):
return self.cards.pop(i)
打印一副牌
>>> deck = Deck()
>>> print(deck)
Ace of Clubs
2 of Clubs
3 of Clubs
4 of Clubs
......
8 of Spades
9 of Spades
10 of Spades
Jack of Spades
Queen of Spades
King of Spades
继承
继承指的是在现有类的基础下进行修改,从而定义新类的能力。例如,假设我们想定义一个类来代表手牌(hand),即玩家目前手里有的牌。类之间有相似之处,但也存在不同,这时就可以用上继承了。你只需要在定义新类时,将现有类的名称放在括号里,即可继承现有类。
class Hand(Deck):
"""代表玩家的一手牌"""
def __init__(self, label=''):
self.cards = []
self.label = label
Hand 的 init 方法会覆盖从 Deck 类继承来的同名方法。
当你创建一个 Hand 时,Python 会调用这个 init 方法,而不是 Deck 中的同名方法。其它方法是从 Deck 继承来的,所以我们可以使用pop_card 和 add_card来发牌
>>> hand = Hand('new hand of porker')
>>> hand.cards
[]
>>> hand.label
'new hand of porker'
>>> deck = Deck()
>>> card = deck.pop_card()
>>> hand.add_card(card)
>>> print(hand)
King of Spades
总结
一个类中的对象可以包含对另外一个类的对象的引用。例如,每一个矩形包含对点的引用,每一个 Deck 包含对许多 Porker 的引用。这种关系被称为组合( HAS-A ),可以类似这样描述:“一个矩形有一个(has a)点”。
一个类可能继承自另外一个类。这种关系被称为继承(IS-A),可以类似这样描述:“Hand is a kind of Deck”。
参考《Think Python 2e》