简体   繁体   中英

My python list comprehension fails due to a syntax error

Python noob using version 3.2.3...

class Card:
    def __init__(self, suitID, rank):
            self.suits = ("Spades", "Hearts", "Diamonds","Clubs")
            self.rank = rank
            self.suit = self.suits[suitID]

    def __str__(self):
            return (str("%s of %s" % (self.rank, self.suit)))


class Deck:
    def __init__(self):
            self.cards = [Card(i//13, i%13) for i in range(52)]

The above is how I have things set up, seems fine to me. The confusion is in the following (please ignore the return ("") statement as this is only for testing)

Case 1:

def __str__(self):
    print ( self.cards [i for i in range (52) ] )
    return("")

Output:

File "cardgame.py", line 21
print (self.cards[i for i in range(52)])
                      ^
SyntaxError: invalid syntax

Why the error? I thought that was how LC's were used...


Case 2:

def __str__(self):
    print (myCards for myCards in self.cards)
return ("")

Output:

<generator object <genexpr> at 0x2256fa0>

Again, what does that mean, and why does it not output the data?


Case 3:

def __str__(self):
    for myCard in self.cards:
          print (myCard)
    return ("")

Output:

0 of Spades
1 of Spades
2 of Spades
3 of Spades
4 of Spades
...
..
.

Now this outputs exactly what I want, but that confuses me ever more. I was under the impression that all three cases are equivalent and they are clearly not. What are the differences?

Thanks in advance.

Case 1:

You should pass an integer rather than i for i in range (52) as the index of a list. Try print [self.cards[i] for i in range(52)] . And you can just write print self.cards if there are only 52 cards in self.cards .

Case 2 & Case 3:

(myCards for myCards in self.cards) is a generator in Python. You can iterate it like a list in Case 3, but it will not return all its elements at first, which is an important feature of generators.

The is is List Comprehensions, you'd better to learn it's gramar.

li = [1,2,3]

la = [i for i in li] # the la is a list [1,2,3]

lb = (i for i in li) # lb is a generator object, and list(lb) is [1,2,3]

in case 1, print [self.cars[i] for i in range(52)] will work.

in your code (self.cars[i for i in range(52)]) , the [i for i in range(52)] is a list,so self.cars[list objeject] is invalid.

print (self.cards[i for i in range(52)])

You are trying to use a list to index into a list. This is like doing the following:

>>> l = [4,5,6]
>>> l[i for i in range (3)]
  File "<stdin>", line 1
    l[i for i in range (3)]

For your first case, that is not how you arrange Python syntax.

print(self.cards[i for i in range (52)])

You are indexing a list with another list . It doesn't make any sense. What you probably meant to do was this:

print([self.cards[i] for i in range(52)])

Note that this just creates a new list . The expression [self.cards[i] for i in range(52)] , operating on a list with 52 elements, has the same result as self.cards . You are adding unnecessary stuff and going in circles.

For your second case, this:

print(myCards for myCards in self.cards)

is printing a generator expression, which is represented as:

<generator object <genexpr> at 0x2256fa0>

For your third case, which prints each item in that object rather than printing the object itself, you can unpack your generator expression above with * and specify a custom separator:

print(*(myCards for myCards in self.cards), sep='\n')

Of course, note that you are once again copying that list for no reason. Just use the original one instead of spending time and effort (both yours and the computer's) making a new one.

print(*myCards, sep='\n')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM