如何在python中重写类定义?
我有一个嵌套的类结构,当我实例化顶级类时,它将一组其他类的对象实例化为属性,而这些对象将一些其他类实例化为自己的属性 在开发代码时,我希望覆盖新模块中的类定义(这对于我来说是一个好方法,可以避免在添加新功能时破坏其他脚本中的现有功能) 作为一个玩具示例,有一个模块,我在其中定义了两个类,其中一个类包含另一个类的列表:Deck和Card。当我实例化一个卡片组对象时,它会实例化一个卡片对象列表 模块_1.py如何在python中重写类定义?,python,Python,我有一个嵌套的类结构,当我实例化顶级类时,它将一组其他类的对象实例化为属性,而这些对象将一些其他类实例化为自己的属性 在开发代码时,我希望覆盖新模块中的类定义(这对于我来说是一个好方法,可以避免在添加新功能时破坏其他脚本中的现有功能) 作为一个玩具示例,有一个模块,我在其中定义了两个类,其中一个类包含另一个类的列表:Deck和Card。当我实例化一个卡片组对象时,它会实例化一个卡片对象列表 模块_1.py class Card(object): def __init__(self, su
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))
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]
我有另一种类型的卡片,我想制作一个卡片组,所以我将卡片组导入一个新模块,并在新模块中定义一个新的卡片类,但是当我实例化卡片组时,它有来自模块_1.py的卡片
模块_2.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))
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>
>python模块_2.py
是否有某种方法可以使用模块_1.py中的甲板类,但让它使用我的新卡类
传递类定义很麻烦,因为实际情况是嵌套的,我可能还想开发顶级对象中包含的其他类
此外,我希望这与面向对象的范例是一致的。是吗?使卡片类成为默认为初始卡片类的卡片组实例初始值设定项的可选参数,并在初始化新卡片组时通过传递第二个卡片类的第二个参数来覆盖它 EDIT使名称更像python,并使索引成为cyphase建议的元组
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))
您的第二个模块将其卡类传递到卡组:
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]
使卡片类成为默认为初始卡片类的卡片组实例初始值设定项的可选参数,并在初始化新卡片组时通过传递第二个卡片类的第二个参数来覆盖它 EDIT使名称更像python,并使索引成为cyphase建议的元组
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))
您的第二个模块将其卡类传递到卡组:
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]
帕特里克的答案是推荐的方法。然而,回答你的具体问题,这实际上是可能的
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
帕特里克的答案是推荐的方法。然而,回答你的具体问题,这实际上是可能的
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
为了使相关类的集合可定制,我不会在类的代码中硬编码一个类选择。相反,我将使用类变量来允许选择备用类
# 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))
及
或者,您最初可以这样编写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))
但这需要在原始模块中的组
之前定义卡
,或者稍后连接到类中,如:
Deck.CardCls = Card
因此,我发现使用以下模式更灵活:
CardCls = self.CardCls or Card
这样,模块中类定义的顺序就无关紧要了。如果所讨论的
Deck
子类的实例有一个变量self.CardCls
set(一个“truthy”值——如果将其设置为子类中的类级变量,它将使用该值)。如果没有,它将使用与组
基类在同一模块中定义的卡
类 为了使相关类的集合可定制,我不会在类的代码中硬编码一个类选项。相反,我将使用类变量来允许选择备用类
# 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))
及
或者,您最初可以这样编写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))
但这需要在原始模块中的组
之前定义卡
,或者稍后连接到类中,如:
Deck.CardCls = Card
因此,我发现使用以下模式更灵活:
CardCls = self.CardCls or Card
这样,模块中类定义的顺序就无关紧要了。如果所讨论的
Deck
子类的实例有一个变量self.CardCls
set(一个“truthy”值——如果将其设置为子类中的类级变量,它将使用该值)。如果没有,它将使用与组
基类在同一模块中定义的卡
类 这比Patrick的答案或我删除的答案更能回答“特定问题”吗?我想,如果您假设OP不想修改Deck
@Cyphase的代码,那么问题是“如何在python中重写类定义?”。下面是如何做到的。确实,这将覆盖卡类定义,而不是修改卡组类,但是您应该提到,它会使原始卡定义无法访问……对于这个用例,这个猴子补丁工作得很好。只希望它不是在多线程的纸牌游戏服务器上,不同的用户选择不同种类的纸牌:-)@Patrick Maupin谢谢你教我猴子补丁这个词!这比Patrick的答案或我删除的答案更能回答“特定问题”吗?我想,如果您假设OP不想修改Deck
@Cyphase的代码,那么问题是“如何在python中重写类定义?”。下面是如何做到的。确实,这将覆盖卡类定义,而不是修改卡组类,但是您应该提到,它会使原始卡定义无法访问……对于这个用例,这个猴子补丁工作得很好。只希望它不是在多线程的纸牌游戏服务器上,不同的用户选择不同种类的纸牌:-)@Patrick Maupin谢谢你教我猴子补丁这个词!另外,self.index
应该是一个元组。非常感谢。这是解决玩具问题的好办法。不幸的是,我有一个更复杂的数据结构,所以名称空间体操更可取。对于这个实现,我需要发送对类定义a的引用