隐式基类object
每个python类都隐式继承object
全文代码实例实现:枚举扑克牌的花色和牌面值
一、_init()__方法:对象初始化
显示而非隐式:__init()__应显示展示初始化变量
对象被实例化时,先创建一个空对象,然后再调用__init()__对对象内部变量或其他内容进行初始化
二、_init()__方法用例:
(一)基类实现初始化
1 class Card: 2 def __init__(self, rank, suit): 3 self.rank = rank 4 self.suit = suit 5 self.hard, self.soft = self._points() 6 7 8 class NumberCard(Card): 9 def _points(self): 10 return int(self.rank), int(self.rank) 11 12 13 class AceCard(Card): 14 def _points(self): 15 return 1, 11 16 17 18 class FaceCard(Card): 19 def _points(self): 20 return 10, 10
- 三个子类共享公共初始化逻辑
- 多态:三个子类对_points(self)都有不同的功能实现
改进:子类实现__init()__方法
1 class Card: 2 def __init__(self, rank, suit, hard, soft): 3 self.rank = rank 4 self.suit = suit 5 self.hard = hard 6 self.soft = soft 7 8 9 class NumberCard(Card): 10 def __init__(self, rank, suit): 11 super().__init__(str(rank), suit, rank, rank) 12 13 14 class AceCard(Card): 15 def __init__(self, rank, suit): 16 super().__init__('A', suit, 1, 11) 17 18 19 class FaceCard(Card): 20 def __init__(self, rank, suit): 21 super().__init__({1: 'A', 11: 'J', 12: 'Q', 13: 'K'}[rank], suit, 10, 10)
super():用于子类要调用父类的同名方法时
单继承:
直接在同名函数中调用super().fun_name()
多继承:
直接在同名函数中调用super(要调用某父类的前一个类名, self).fun_name()
(二)创建常量清单
# 牌的字符与名称 class Suit: def __init__(self, name, symbol): self.name = name self.symbol = symbol
1 Club, Diamond, Heart, Spade = Suit('Club', 'C'), Suit('Diamond', 'D'), 2 Suit('Heart', 'H'), Suit('Spade', 'S')
二、工厂函数
实现工厂函数的两种途径
- 定义一个函数,返回不同类的对象
- 定义一个类,包含创建对象的方法
途径一:
1 def card1(rank, suit): 2 if rank == 1: 3 return AceCard('A', suit) 4 elif 2 <= rank <= 10: 5 return NumberCard(str(rank), suit) 6 elif rank == 11: 7 return FaceCard('J', suit) 8 elif rank == 12: 9 return FaceCard('Q', suit) 10 elif rank == 13: 11 return FaceCard('K', suit)
上述函数实现了牌面值与花色的对应
三、使用映射和类来简化设计
(一)并行映射
1 def card2(rank, suit): 2 # 在集合中查找rank, 未查到到返回NumberCard 3 class_ = {1: AceCard, 11: FaceCard, 12: FaceCard, 13: FaceCard}.get(rank, 4 NumberCard) 5 rank_str = {1: 'A', 11: 'J', 12: 'Q', 13: 'K'}.get(rank, str(rank)) 6 return class_(rank_str, suit)
缺点:映射键1、11、12、13逻辑重复,使用两次映射来获取牌面值和花色。重复的代码是多余的,提高了维护成本
(二)二元组映射
1 # 二元组映射 2 def card3(rank, suit): 3 class_, rank_str = {1: (AceCard, 'A'), 11: (FaceCard, 'J'), 12: (FaceCard, 'Q'), 4 13: (FaceCard, 'K')}.get(rank, (NumberCard, str(rank))) 5 return class_(rank_str, suit)
(三)partial函数:偏函数
使用方法:调用函数fun_name(arg1,arg*.....)
fun_name1=partial(fun_name, arg1…)
fun_name1(arg*…) 偏函数
from functools import partial def card4(rank, suit): part_class = {1: partial(AceCard, 'A'), 11: partial(FaceCard, 'J'), 12: partial(FaceCard, 'Q'), 13: partial(FaceCard, 'K')} .get(rank, partial(NumberCard, str(rank))) return part_class(suit)
(四)工厂流畅API
结合二元组映射实现API,该对象顺序调用
1 class CardFactory: 2 def rank(self, rank): 3 self.class_, self.rank_str = { 4 1: (AceCard, 'A'), 5 11: (FaceCard, 'J'), 6 12: (FaceCard, 'Q'), 7 13: (FaceCard, 'K') 8 }.get(rank, (NumberCard, str(rank))) 9 return self 10 11 def suit(self, suit): 12 return self.class_(self.rank_str, suit)