Reputation: 201
I have the following class of a card:
class Card:
def __init__(self, number, position):
self.number = number
self.position = position * 50
self.rect = pg.Rect(self.position, 0, 50, 100)
def draw(self, surface):
pg.draw.rect(surface, green, (self.position, 0, 50, 100))
## pg.draw.rect(surface, green, self.rect)
And I'd like to create 16 different cards side by side, from 0 to 800, each one with width=50. Their numbers would be 0 to 7 and then 0 to 7 again. I already came up with a solution for this problem, which is:
cards = []
for n in range(16):
cards.append(Card(n%8, n))
However, broken solutions that appeared along the way left me with unanswered questions. For example:
cards = [Card(n, 0) for n in range(8)] * 2
for n in range(16):
cards[n].position = n * 50
Here, I realized that cards[0] is cards[8]
returns True
. The result is that only the last half of the cards appears on screen. Apparently that is the same thing that happens in:
cards = [Card(n, 0) for n in range(8)]
cards.extend(cards)
But I thought changing the second line to:
cards.extend(cards[:])
would solve the issue making a copy and not a reference, but it still doesn't work. That is something I wanted an explanation. Is there an easy way to fix this copy vs. reference issue in the previous 2 cases?
One other issue is the commented version of the draw method. In some of the broken methods I used, this version doesn't work because it never updates the position, which is always stuck in 0. It seems that outside the class, card.rect[0]
doesn't receive the value of card.position
, although I can use self.position
directly inside the draw method. What's going on with the self.rect
here?
EDIT
My second issue is solved here: How do you change the value of one attribute by changing the value of another? (dependent attributes)
Upvotes: 2
Views: 78
Reputation: 210968
The loop
cards = [] for n in range(16): cards.append(Card(n%8, n))
runs 16 times. Hence there are constructed 16 Card
objects and append to a list. Finally you get 16 separate instances of the class Card
and a list with 16 elements.
But the expression
cards = [Card(n, 0) for n in range(8)] * 2
does not create 16 Card
objects. It constructs 8 Card
objects and a list with 16 elements, where each object is contained twice. Card (n, 0)
is only invoked 8 times, so there can only be 8 instances of Card
.
The same applies to
cards.extend(cards[:])
[:]
creates a shallow copy of a list. The list just contains references to the objects. The list respectively the references to the objects are copied, but the objects themselves are not copied, but no new Card
object is created.
Upvotes: 2
Reputation: 311
This relates to how Python stores integers. The "common" integers from -5 to 255 are already stored in memory. When you assign a variable like a = 1
, you are creating a pointer to the "hard coded" integer 1
already in memory, not instantiating a new integer. Any time you create an integer within this range, it will not be a new number so this will work:
>>> a = 7
>>> b = 7
>>> a is b
True
Whereas for a number outside of this range:
>>> a = 1234
>>> b = 1234
>>> a is b
False
Thus:
>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a[0] is b[0]
True
>>> a is b
False
Upvotes: -1