-1

So I'm trying to compare a Deck object with the evaluated representation of a Deck object and getting

Traceback (most recent call last):
  File "C:/Users/Philipp/PycharmProjects/fnaround/src.py", line 3, in <module>
    print(Deck() == eval(repr(Deck())))
  File "<string>", line 1, in <module>
NameError: name 'Card' is not defined

I can not figure out what it is as I also have overridden the __repr__ method in other classes and it works fine. I think it has something to do with it jumping from the Deck class to the Card class but I'm not sure. Can someone explain to me how the program is moving through the classes and how to fix the error. Thanks

class Deck:

    suits = ['\u2660', '\u2661', '\u2662', '\u2663']
    ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']

    def __init__(self):

        self.deck = []

        for suit in self.suits:
            for rank in self.ranks:
                self.deck.append(Card(rank, suit))

    def __repr__(self):
        return 'Deck({})'.format(self.deck)

    def __eq__(self, other):
        return self.deck == other.deck

class Card:

    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit

    def __repr__(self):
        return "Card('{}', '{}')".format(self.rank, self.suit)

    def __eq__(self, other):
        return self.rank == other.rank and self.suit == other.suit

print(Deck() == eval(repr(Deck())))
Blckknght
  • 100,903
  • 11
  • 120
  • 169
phil
  • 403
  • 2
  • 7
  • 2
    Please fix your indentation. Also, why are you importing classes that are right there? – kindall Sep 20 '16 at 20:02
  • @kindall I assume that in the real program, these are two separate files. – Barmar Sep 20 '16 at 20:07
  • @kindall yes they are separate files. sorry removed the import statements – phil Sep 20 '16 at 20:10
  • Is your last line with the `print` really embedded inside the `Card` class? That's certainly going to cause you some issues, though exactly which ones will depend on how you're doing your imports as well. In any case, since you're describing an exception, please include the full traceback. – Blckknght Sep 20 '16 at 20:11
  • 2
    Please post the entire error traceback, _including the line of code which caused the error_. You're making us guess where the error actually occurs. – John Gordon Sep 20 '16 at 20:12
  • It's probably not what's causing your current error (which is probably some combination of circular imports and bad indentation), but the `repr` of your `Deck` won't work when `eval`'d because `Deck.__init__` never takes any extra arguments. – Blckknght Sep 20 '16 at 20:15
  • @Blckknght no it wasn't supposed to be in there. Sorry. And why does Deck.__init__ need extra args? – phil Sep 20 '16 at 20:24
  • `Deck.__repr__` returns a string like `Deck([Card('A', '♠')])`. But that's not a valid expression you can `eval`, since `Deck` doesn't accept any arguments (it always creates a fresh set of `Card`s). So even if you sort out your `NameError`, you're going to have other issues with your `eval` call. – Blckknght Sep 20 '16 at 20:26
  • Can you clarify how exactly the different parts of your code are separated out into different files? The `NameError` you're getting suggests that when the last line of the code is run, you have access to the name `Deck`, but not `Card`, which doesn't make any sense the way you've shown the code in one big block. – Blckknght Sep 20 '16 at 20:32
  • @Blckknght Deck class imports the Card class. Main class imports Deck class – phil Sep 20 '16 at 20:36
  • One final comment about the overall issue: In Python, modules are most useful if they combine all the closely related objects into one namespace. There's no need to put every single class in it's own module, and indeed (as you're seeing here), it makes everything awkward in some situations. – Blckknght Sep 20 '16 at 21:56

3 Answers3

0

Your Deck class takes no arguments, but your representation passes a list of cards as argument. You can change your Deck.__init__ to something like this:

def __init__(self, deck=None):
    if deck:
        self.deck = deck
    else:
        self.deck = [Card(r, s) for r in self.ranks for s in self.suits]

And the final comparison should also work as you expect.

Pedro Werneck
  • 40,902
  • 7
  • 64
  • 85
0

I get this output;

deck.py", line 32, in <module>
  print(Deck() == eval(repr(Deck())))
File "<string>", line 1, in <module>
TypeError: __init__() takes 1 positional argument but 2 were given
<<< Process finished. (Exit code 1)

Your repr is trying to pass a second argument to Deck__init__(). It only takes one. This works

def __repr__(self):
    return 'Deck()'.format(self.deck)
CAB
  • 1,106
  • 9
  • 23
0

The current issue (causing the NameError) is that when you're running the eval on a Deck instance's repr, you don't have the name Card in the local namespace. This means that When eval tries to interpret the string that repr(Deck()) returns, it fails when it comes across the first Card.

You can fix this part of the problem simply by importing Card as well as Deck into the namespace where you're running the other code:

from deck_module import Deck  # you've not said what your module names are,
from card_module import Card  # so I'm making these up

eval(repr(Deck())) # raises a TypeError, but not a ValueError any more

Adding the import of the Card class doesn't make the code work (due to shortcomings of the Deck constructor), but at least it will get you past the NameError.

Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • Got it to work but I don't understand why I also have to import Card if it's already imported into Deck – phil Sep 20 '16 at 21:06
  • You need it for the `eval`, since that happens in your current namespace. Just look at what `repr(Deck())` is, and see what would happen if you typed it in without importing `Card` first. – Blckknght Sep 20 '16 at 21:54