我有一个嵌套的类结构,当我实例化顶级类时,它将一堆其他类的对象实例化为属性,并将那些其他类实例化为它们自己的属性。
在我开发代码时,我希望在新模块中覆盖类定义(这对我来说是一种很好的方法,可以避免在添加新功能时破坏其他脚本中的现有功能)。
作为一个玩具示例,有一个模块,我定义了两个类,其中一个有另一个列表,Deck和Card。当我实例化一个Deck对象时,它会实例化一个Card对象列表。
module_1.py
class Card(object):
def __init__(self, suit, number):
self.suit = suit
self.number = number
class Deck(object):
def __init__(self):
suit_list = ['heart', 'diamond', 'club', 'spade']
self.cards = []
for suit in suit_list:
for number in range(14):
self.cards.append(Card(suit, number))
我有另一种类型的卡,我想制作那些卡片,所以我将Deck导入新模块并在新模块中定义一个新的Card类,但是当我实例化Deck时,它有来自module_1的卡片。吡啶
module_2.py
from module_1 import Deck
class Card(object):
def __init__(self, suit, number):
self.suit = suit
self.number = number
self.index = [suit, number]
if __name__ == '__main__':
new_deck = Deck()
print new_deck.cards[0]
输出:
>python module_2.py
<module_1.Card object at 0x000001>
我是否可以通过某种方式从module_1.py中使用我的Deck类,但让它使用我的新Card类?
传递类定义很麻烦,因为实际情况是深层嵌套的,我可能还想开发顶级对象中包含的其他类。
另外,我希望这与面向对象的范例一致。是吗?
答案 0 :(得分:4)
使Card类成为Deck实例初始化程序的可选参数,默认为初始Card类,并在初始化新卡片组时通过传递第二个Card类的第二个参数来覆盖它。
编辑根据cyphase的建议,使名称更加Pythonic并使索引成为元组。
class Card(object):
def __init__(self, suit, number):
self.suit = suit
self.number = number
class Deck(object):
def __init__(self, card_type=Card):
suit_list = ['heart', 'diamond', 'club', 'spade']
self.cards = []
for suit in suit_list:
for number in range(14):
self.cards.append(card_type(suit, number))
您的第二个模块会将其Card类传递到Deck:
from module_1 import Deck
class FancyCard(object):
def __init__(self, suit, number):
self.suit = suit
self.number = number
self.index = suit, number
if __name__ == '__main__':
new_deck = Deck(FancyCard)
print new_deck.cards[0]
答案 1 :(得分:0)
import module_1
class Card(object):
def __init__(self, suit, number):
self.suit = suit
self.number = number
self.index = [suit, number]
if __name__ == '__main__':
# Keep reference to the original Card class.
original_card = module_1.Card
# Replace with my custom Card class.
module_1.Card = Card
new_deck = module_1.Deck()
print new_deck.cards[0]
# Restore.
module_1.Card = original_card
答案 2 :(得分:0)
为了使相互关联的类的集合可以自定义,我不会硬编码类的代码中的类选择。相反,我会使用类变量来选择替代类。
# module 1
class Card(object):
def __init__(self, suit, number):
self.suit = suit
self.number = number
class Deck(object):
CardCls = None
def __init__(self, card_type=Card):
suit_list = ['heart', 'diamond', 'club', 'spade']
self.cards = []
CardCls = self.CardCls or Card
for suit in suit_list:
for number in range(14):
self.cards.append(CardCls(suit, number))
和
# module 2
from module_1 import Deck
class NewCard(object):
def __init__(self, suit, number):
self.suit = suit
self.number = number
self.index = [suit, number]
class NewDeck(Deck):
CardCls = NewCard
或者,您最初可以代之以Deck
代码:
class Deck(object):
CardCls = Card
def __init__(self, card_type=Card):
suit_list = ['heart', 'diamond', 'club', 'spade']
self.cards = []
for suit in suit_list:
for number in range(14):
self.cards.append(self.CardCls(suit, number))
但是这需要在原始模块中Card
之前定义Deck
,或者稍后将其连接到类中:
Deck.CardCls = Card
因此,我发现使用类似的模式更灵活:
CardCls = self.CardCls or Card
这样,模块中类定义的顺序无关紧要。如果所讨论的Deck
子类的实例具有变量self.CardCls
设置(“truthy”值 - 如果将其设置为子类中的类级变量,它将使用它)将使用那。如果没有,它将使用与Card
基类相同的模块中定义的Deck
类。