__repr__ 和 python 拆包
__repr__ and python unpacking
我正在尝试使用 classes 在 python 项目中打印玩家的手。
(在非常沮丧之后,我用谷歌搜索了如何通过解包来做到这一点)
有没有人能举例说明我如何使用 __repr__
简单地打印此列表?可以将 __init__
换成 __repr__
吗?是否应该使用另一个函数来添加从 class 打印列表的功能?
例如,为什么下面的解包可以工作,但没有解包就不行?
>>> print(*test_player.cards, sep='\n')
Ace of Clubs
King of Clubs
>>> print(test_player.cards)
[<__main__.Card object at 0x000001E2BA608388>, <__main__.Card object at 0x000001E2BA608488>]
我的代码主体如下:
suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King', 'Ace')
values = {'Two':2, 'Three':3, 'Four':4, 'Five':5, 'Six':6, 'Seven':7, 'Eight':8,
'Nine':9, 'Ten':10, 'Jack':10, 'Queen':10, 'King':10, 'Ace':11}
class Card:
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
def __str__(self):
return self.rank + ' of ' + self.suit
class Deck:
def __init__(self):
self.deck = [] # start with an empty list
for suit in suits:
for rank in ranks:
self.deck.append(Card(suit,rank))
def __str__(self):
deck_comp = '' # start with an empty string
for card in self.deck:
deck_comp += '\n '+card.__str__() # add each Card object's print string
return 'The deck has:' + deck_comp
def shuffle(self):
random.shuffle(self.deck)
def deal(self):
single_card = self.deck.pop()
return single_card
class Hand:
def __init__(self):
self.cards = [] # start with an empty list as we did in the Deck class
self.value = 0 # start with zero value
self.aces = 0 # add an attribute to keep track of aces
def add_card(self,card):
self.cards.append(card)
self.value += values[card.rank]
test_player=Hand()
test_deck=Deck()
test_player.add_card(test_deck.deal())
test_player.add_card(test_deck.deal())
在你的 Card
class 中定义一个 __repr__
:
def __repr__(self):
return str(self)
然后你的 Deck
可以简单地做:
def __str__(self):
return str(self.deck)
当您使用列表调用 str()
时,它会为列表的各个元素调用 repr()
并使用熟悉的 [foo, bar, baz]
格式对它们进行格式化。
当你打印一个列表时,它的 repr 包括每个元素的 repr,所以为你的 Card
class 创建一个 __repr__
方法。 The __repr__
method should show info you can use for debugging,如果它显示了如何构建对象就更好了,所以我会使用这个:
def __repr__(self):
return f'{type(self).__name__}({self.suit!r}, {self.rank!r})'
所以现在我们得到这个:
>>> print(test_player.cards)
[Card('Clubs', 'Ace'), Card('Clubs', 'King')]
我还会在 Deck
中添加一个 __repr__
,虽然我们无法展示它的结构,所以我会使用这个:
def __repr__(self):
return f'<{type(self).__name__}: deck={self.deck!r}>'
为了简单起见,现在我只得到最后两个元素,然后检查 repr:
>>> test_deck.deck = test_deck.deck[-2:]
>>> test_deck
<Deck: deck=[Card('Clubs', 'Jack'), Card('Clubs', 'Queen')]>
您可以对 Hand
使用类似的东西:
def __repr__(self):
return f'<{type(self).__name__}: cards={self.cards!r}>'
>>> test_player
<Hand: cards=[Card('Clubs', 'Ace'), Card('Clubs', 'King')]>
顺便说一句,您可以考虑让 Deck
继承自 list
以避免笨拙 Deck.deck
,并让它直接支持索引等等。
我正在尝试使用 classes 在 python 项目中打印玩家的手。
(在非常沮丧之后,我用谷歌搜索了如何通过解包来做到这一点)
有没有人能举例说明我如何使用 __repr__
简单地打印此列表?可以将 __init__
换成 __repr__
吗?是否应该使用另一个函数来添加从 class 打印列表的功能?
例如,为什么下面的解包可以工作,但没有解包就不行?
>>> print(*test_player.cards, sep='\n')
Ace of Clubs
King of Clubs
>>> print(test_player.cards)
[<__main__.Card object at 0x000001E2BA608388>, <__main__.Card object at 0x000001E2BA608488>]
我的代码主体如下:
suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King', 'Ace')
values = {'Two':2, 'Three':3, 'Four':4, 'Five':5, 'Six':6, 'Seven':7, 'Eight':8,
'Nine':9, 'Ten':10, 'Jack':10, 'Queen':10, 'King':10, 'Ace':11}
class Card:
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
def __str__(self):
return self.rank + ' of ' + self.suit
class Deck:
def __init__(self):
self.deck = [] # start with an empty list
for suit in suits:
for rank in ranks:
self.deck.append(Card(suit,rank))
def __str__(self):
deck_comp = '' # start with an empty string
for card in self.deck:
deck_comp += '\n '+card.__str__() # add each Card object's print string
return 'The deck has:' + deck_comp
def shuffle(self):
random.shuffle(self.deck)
def deal(self):
single_card = self.deck.pop()
return single_card
class Hand:
def __init__(self):
self.cards = [] # start with an empty list as we did in the Deck class
self.value = 0 # start with zero value
self.aces = 0 # add an attribute to keep track of aces
def add_card(self,card):
self.cards.append(card)
self.value += values[card.rank]
test_player=Hand()
test_deck=Deck()
test_player.add_card(test_deck.deal())
test_player.add_card(test_deck.deal())
在你的 Card
class 中定义一个 __repr__
:
def __repr__(self):
return str(self)
然后你的 Deck
可以简单地做:
def __str__(self):
return str(self.deck)
当您使用列表调用 str()
时,它会为列表的各个元素调用 repr()
并使用熟悉的 [foo, bar, baz]
格式对它们进行格式化。
当你打印一个列表时,它的 repr 包括每个元素的 repr,所以为你的 Card
class 创建一个 __repr__
方法。 The __repr__
method should show info you can use for debugging,如果它显示了如何构建对象就更好了,所以我会使用这个:
def __repr__(self):
return f'{type(self).__name__}({self.suit!r}, {self.rank!r})'
所以现在我们得到这个:
>>> print(test_player.cards)
[Card('Clubs', 'Ace'), Card('Clubs', 'King')]
我还会在 Deck
中添加一个 __repr__
,虽然我们无法展示它的结构,所以我会使用这个:
def __repr__(self):
return f'<{type(self).__name__}: deck={self.deck!r}>'
为了简单起见,现在我只得到最后两个元素,然后检查 repr:
>>> test_deck.deck = test_deck.deck[-2:]
>>> test_deck
<Deck: deck=[Card('Clubs', 'Jack'), Card('Clubs', 'Queen')]>
您可以对 Hand
使用类似的东西:
def __repr__(self):
return f'<{type(self).__name__}: cards={self.cards!r}>'
>>> test_player
<Hand: cards=[Card('Clubs', 'Ace'), Card('Clubs', 'King')]>
顺便说一句,您可以考虑让 Deck
继承自 list
以避免笨拙 Deck.deck
,并让它直接支持索引等等。