Python __str__ and lists
Calling string on a python list calls the __repr__
method on each element inside. For some items, __str__
and __repr__
are the same. If you want that behavior, do:
def __str__(self):
...
def __repr__(self):
return self.__str__()
__str__ method on list of objects
You just need to replace the __str__
method of the PlayingCard
class with a __repr__
method:
class PlayingCard():
def __init__(self,value,suit):
self.value = value
self.suit = suit
def __repr__(self):
return '{} of {}'.format(Value(self.value).name, Suit(self.suit).name)
Alternatively you can change the __str__
method in the Deck
class to get the string representation of every card:
class Deck():
def __init__(self):
self.cards=[PlayingCard(val,suit) for val in Value for suit in Suit]
def __str__(self):
return str([str(card) for card in self.cards])
Then you get the correct output with:
...
deck = Deck()
print(deck)
Output:
(The 2nd way will add quotes around every printed card)
[Two of Spades, Two of Hearts, Two of Clubs, Two of Diamonds, Three of
Spades, Three of Hearts, Three of Clubs, Three of Diamonds, Four of
Spades, Four of Hearts, Four of Clubs, Four of Diamonds, Five of
Spades, Five of Hearts, Five of Clubs, Five of Diamonds, Six of
Spades, Six of Hearts, Six of Clubs, Six of Diamonds, Seven of Spades,
Seven ofHearts, Seven of Clubs, Seven of Diamonds, Eight of Spades,
Eight of Hearts, Eight of Clubs, Eight of Diamonds, Nine of Spades,
Nine of Hearts, Nine of Clubs, Nine of Diamonds, Ten of Spades, Ten of
Hearts, Ten of Clubs, Ten of Diamonds, Jack of Spades, Jack of Hearts,
Jack of Clubs, Jack of Diamonds, Queen of Spades, Queen of Hearts,
Queen of Clubs, Queen of Diamonds, King of Spades, King of Hearts,
King of Clubs, King of Diamonds, Ace of Spades, Ace of Hearts, Ace of
Clubs, Ace of Diamonds]
When you call __str__
on a list
object, it will go through every element of the list and call __repr__
on that object to get its representation.
So when you call print(deck)
, you get:
--> deck.__str__()
--> str(self.cards)
--> [card.__repr__() for card in self.cards]
Confused about __str__ on list in Python
Python has two different ways to convert an object to a string: str()
and repr()
. Printing an object uses str()
; printing a list containing an object uses str()
for the list itself, but the implementation of list.__str__()
calls repr()
for the individual items.
So you should also overwrite __repr__()
. A simple
__repr__ = __str__
at the end of the class body will do the trick.
How do I use __str__ method to print list?
__repr__
and __str__
serves different purposes but work the same way.
You can read this to help you chose between the two methods.
You can change the __str__
method of the Hand class like this :
class Hand:
def __str__(self):
hand_tostr = ', '.join(map(str, self.cards)) # I use map to apply str() to each element of self.cards
return 'The {} is composed by {}'.format(self.label, hand_tostr)
If you want to change the __repr__
method of the Card class, you can try something like this (you didn't provide the code for the Card class)
class Card:
#your code
def __repr__(self):
return <some string>
Now if you do str(<list of Card objects>)
it will use the __repr__
method on each card instance to display what you want. I am not a big fan of this solution, for your case I would use the first one as you may want to keep the default representation of a card object for other cases.
Be careful with this code :
def add_card(self,card):
if isinstance(card, Card): #check if card belongs to card Class!!
self.cards.append(card)
You don't raise anything if card is not an instance of Card. That means if you use this method with the wrong parameter, error will be hidden and you won't know that the deck has not changed. This is quite dangerous. You can do something like this instead:
def add_card(self,card):
assert(isinstance(card, Card)), "card parameter of add_card must be an instance of Card class"
self.cards.append(card)
In a more pythonic way, you can use typehint to inform the user of your classes that card should be an instance of Card. Then trust the duck-typing style of python, or use tools like mypy to verify that the method is correctly used.
Is there a way to use __str__ in a class but returning a list?
The builtin str()
function will raise a TypeError
if it calls your __str__
and gets something that isn't a string, and you won't convince it to do otherwise.
What you probably want is for Vec.__str__
to return the string representation of data
, rather than data
itself:
class Vec:
def __init__(self, data: list) -> None:
self.data = data
def __str__(self) -> str:
return str(self.data)
The __str__
method has no bearing on your other use case:
for example if I want to multiply
Mat
with aVec
I would have to doMat * Vec.data
orMat * Vec.T
(T stands for transposed) which I dont like and I would just like to typeMat * Vec
in case I dont need to transpose the vector.
This should instead be addressed in Mat.__mul__
(which should operate on a Vec
, not the underlying list
) and Vec.T
/Vec.Transpose
(which should return a Vec
, not a list
):
class Vec:
...
def Transpose(self) -> 'Vec':
vec = self.Create(len(self.data), len(self.data[0]), 0)
for i in range(len(self.data)):
for j in range(len(self.data[0])):
vec[j][i] = self.data[i][j]
return Vec(vec)
class Mat:
...
def __mul__(self, vec: Vec) -> list[list[int]]:
if not self.CheckRowCol(vec.data):
raise MatrixRowColError
mat3 = self.Create(len(vec.data[0]), len(self.data), 0)
for i in range(len(self.data)):
for j in range(len(vec.data[0])):
for k in range(len(self.data[0])):
mat3[i][j] += self.data[i][k] * vec.data[k][j]
return mat3
Now you can indeed do Mat * Vec
or Mat * Vec.T
and it will do the right thing.
Note that it would probably be better for Mat.__mul__
to return a Mat
, but you haven't provided a constructor that makes it easy for me to implement that part -- nevertheless I hope this gives you a better way to think about your class interfaces and how they can make it easier (or harder) to use the class! Ideally the user of the class shouldn't even be able to access the internals, much less be forced to.
Unrelated to this, I'd suggest spending a bit of time learning about Python's list comprehension syntax, because it'll save you a lot of list allocation boilerplate (i.e. your various Create
methods). :)
How to apply __str__ function when printing a list of objects in Python
Try:
class Test:
def __repr__(self):
return 'asd'
And read this documentation link:
Python - __str__ returning elements of a list
Suppose this is your Card
class:
class Card(object):
# has self.value and self.suit
def __str__(self):
return (str(self.value) + self.suit)
So your player class is something like this:
class Player(object):
# has self.card1, self.card2
def __str__(self):
return "Player's Cards %s %s (Total %d)" % (
self.card1, self.card2, self.__sum_of_cards()
)
So, all you need is to add the missing method __sum_of_cards
in Player
:
def __sum_of_cards(self):
return self.card1.value + self.card2.value
You could do this directly in __str__
instead of implementing __sum_of_cards
, but I'm assuming it means something if you're printing it, and that implies it will be needed elsewhere as well.
Edit:
Same goes for lists:
class Player(object):
# has self.hand
def __str__(self):
return "Player's Cards %s (Total %d)" % (
",".join(str(card) for card in self.hand),
self.__sum_of_hand()
)
But a different __sum_of_hand
is needed:
def __sum_of_hand(self):
return sum(x.value for x in self.hand)
Related Topics
Returning the Product of a List
Isprime Function for Python Language
How to Expand a List to Function Arguments in Python
Matplotlib Colorbar for Scatter
Intersection of Two Graphs in Python, Find the X Value
Run a Program from Python, and Have It Continue to Run After the Script Is Killed
How to Shift a Column in Pandas Dataframe
Insert an Element at a Specific Index in a List and Return the Updated List
Is the Time-Complexity of Iterative String Append Actually O(N^2), or O(N)
Filtering a List of Strings Based on Contents
How to Intercept Calls to Python's "Magic" Methods in New Style Classes
How to Dynamically Change Base Class of Instances at Runtime
How to Get the Utc Time of "Midnight" for a Given Timezone
Does Python Support MySQL Prepared Statements
Python Split() Without Removing the Delimiter