4

Can someone explain to me how to return a new instance of a class by iterating over a list of names and a list of dicts?

I know that I can unpack my dictionary using **, and I know that I can iterate through my list of dictionaries.

So I attempted to create a for loop function that creates new instances of my Card class for each card in the cardList.

Here is the code I thought would work:

def createCardInstances(x):
    for i in range(len(x)):
        namesOfCards[i] = Card(**cardList[i])
        return namesOfCards[i]

namesOfCards is a list of card names that I would like to turn into instances of the Card class. cardList is a list of the dictionaries that represent cards and their values.

For instance, I can do this:

Knight = Card(**cardList[0])

Which works fine. But, if I'm developing a card game and have upwards of a 100 individual cards or more, I would like to avoid having to write out each card name individually and copy\pasting the =Card(**cardList[]) code each time.

How do I automate the creation of new instances? Is that even feasible?


EDIT:

I'm trying to use the names in namesOfCards to make new instances of Card. It was suggested to me that my next step in learning python while creating a card game was to make it more object oriented.

So my goal right now is to use the names of the cards - saved in the list namesOfCards - to make new instances of Card. i.e.:

[Knight, Mage, Warrior, ...]

And I want to have the ability to take those and do this:

Knight = Card(**cardList[0])

Mage = Card(**cardList[1])

Warrior = Card(**cardList[2]

and so on and so forth.

Is that possible? Or do I need to use the list comprehension suggestion to store all of the class instances into a list, and then have to access the instances by using new_cards[0].name or new_cards[1].attack?

4
  • What error are you getting? could be that you should have **(cardList[i]) Commented May 29, 2013 at 17:20
  • If I try to reference an instance that I think is created, i.e. Knight or Mage by calling print Knight.attack - I get NameError: name 'Knight' is not defined. Commented May 29, 2013 at 17:23
  • What do you expect createCardInstances to return? Because right now, it's returning a single Card after a single iteration of your loop, and no other Card gets a chance to be initialized. Commented May 29, 2013 at 17:24
  • Right, I understand that it's only returning one "card" instance. That was my first attempt at making a function that creates all of the card instances using a loop. What I don't know is how to make that code return more than 1 new card instance. Add them to a list? If so, how do you access instances from lists? Commented May 29, 2013 at 17:27

2 Answers 2

2

you are returning an individual card when you pass it a list? also if cardNames is a list of names you shouldn't be overwriting it with Card objects. You should be able to do something like this?

new_cards = [Card(**card) for card in card_list]  # make new card objects
cards = {card.name: card for card in new_cards}  # dict to ref cards by name 
print cards['Knight'].name

or simply

cards = {card['name']: Card(**card) for card in card_list}

if you are wanting to restrict that cards to only those in namesOfCards. you could

cards = {card['name']: Card(**card) for card in card_list if card['name'] in names_of_cards}

(note: this all assumes that you dont have two cards with the same name)

It is also possible to put those cards into your local namespace like the question asks, but I would highly discourage it. But if you really really want to ...

locals().update(cards)
print Knight.name
Sign up to request clarification or add additional context in comments.

5 Comments

Ok, so this creates a list of the instances using list comprehension, correct? Is there a way to do this in such a way that I can call print Knight.name to print Knight instead of print new_cards[0].name?
@bhamhawker you could use an attrdict and add your cards to it based on name, then you could reference them like that or just with a dict and use [name]
@bhamhawker: well if you want each card to have a name and a value, then I'd suggest using a dictionary instead of a list because that's what they are made for.
@cmd: Why is it discouraged to update the local namespace as such? I'm just learning pythonic ways as I go, so I'd like to avoid anything that would be discouraged by more seasoned coders than I.
Because it becomes really easy to stomp local variables that happen to be called the same thing as your card name. Also you start having variable names based on data, this blurs the separation of logic and data. Also in general it doesn't buy you anything (other then slightly less typing). It is usually more convenient to have them in a dict and then you can use variables to reference the card based on name.
1

make sure that your list contains string like

CARDS = ['Knght', 'Mage'] #and so on

I'm not sure if this is what you need but see the code below:

CARD = ['knight','mage']

class cards:
    def __init__(self, name):
        self.n = name
        self.attack = "attack " + self.n

print knight.attack

using that you can loop through a list or dictionary to create an instance of your class

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.