Python add class to list

Python class objects appending to list

I have a list of class objects that I would like to distribute to other lists as objects and then these lists should be called to provide interaction with the objects within. The issue that I cannot overcome at the moment is when trying to append the objects with a for loop from the first list to the second one and instead getting the new list populated with the class objects I get their pointers to the memory. This is currently running on Python 3.x if any difference. I have seen some cases where the suggestion is to play with __str__ and
__repr__ but I don’t come to a solution for my case.

class Robot(): """Test class""" def __init__(self, age): self.age = age r = Robot(10) r1 = Robot(15) mylist1 = [r, r1] mylist2=[] for item in mylist1: mylist2.append(item) print(mylist2) 

Well, the problem is the missing __str__ or __repr__ method; without is, that’s just how Python represents those instances. Apart from that, your code works correctly.

There isn’t really a way to do this. Think about it like this: What if you initialized myList1 like myList1 = [Robot(10), Robot(15)] . What should it print? The variable names aren’t a part of the object. They’re a separate label associated with the object. The objects don’t know what variables names they’ve been given.

Those two items are exactly r and r1 : just their string representation (which defaults to this, since you haven’t defined a string representation yourself for the class).

Читайте также:  404 error in php page

There’s nothing wrong here: you are appending instances of Robot , which are indeed located elsewhere in memory, and you only have pointers to them. This is how Python works. If you would like the string representation of these objects to be different, read about __repr__ .

r and r1 are variable names. They are not the robots themselves. They are just labels, post-it nodes stuck on the robots, and you can add as many of those post-it notes as you want. But you are adding the robots themselves to the list, not those names. See nedbatchelder.com/text/names.html for more information on how Python names work. If you want your robots to be shown in a list with a name, you need to explicitly give the robots names (as a attribute of the robot itself), and use __repr__ to create a string to be shown when printing a list, where you include the names.

Источник

How to append class object to list

After instantiating a deck ( deck = Deck() ), calling deck.show_deck() just prints out «two of diamonds» 52 times. The ‘copy’ part is as per this answer, but doesn’t seem to help. Any suggestions?

import copy from card import Card class Deck: card_ranks = ['ace','king','queen','jack','ten','nine','eight','seven','six','five','four','three','two'] card_suites = ['clubs','hearts','spades','diamonds'] deck = [] def __init__(self): #create a deck of 52 cards for suite in Deck.card_suites: for rank in Deck.card_ranks: Deck.deck.append(copy.deepcopy(Card(card_rank=rank, card_suite=suite))) def show_deck(self): for item in Deck.deck: print item.get_name() 
class Card: card_name = '' def __init__(self, card_rank, card_suite): self.card_rank = card_rank.lower() self.card_suite = card_suite.lower() Card.card_name = card_rank + " of " + card_suite def get_name(self): return Card.card_name 

I would create a temporary list first that contains all the cards then after that deepcopy the temporary list to deck

You don’t show your Card code here, but why do you need a deepcopy , particularly if you’re instantiating it for the first time? Something isn’t right here.

@user2372996 Yes the temporary list would go in __init__ but I can’t help but think there’s a design problem here because you really shouldn’t need a deepcopy here. As for the cause of why the code in your question doesn’t work I’m just trying to get my head around that right now.

2 Answers 2

The problem here is that the Card class has a name variable which is shared with all instances of the Card class.

This means that all Card objects will have the same name ( card_name ) which is almost surely not what you want.

You have to make the name be part of the instance instead like so:

class Card: def __init__(self, card_rank, card_suite): self.card_rank = card_rank.lower() self.card_suite = card_suite.lower() self.card_name = card_rank + " of " + card_suite def get_name(self): return self.card_name 

You will find that the deepcopy is not needed, nor was it ever needed, but it does show you that deepcopy will not allow you to keep different states of class variables.

Further I would recommend you change Card to have it’s own __str__ method if you want to print it out:

class Card: def __init__(self, card_rank, card_suite): self.card_rank = card_rank.lower() self.card_suite = card_suite.lower() def __str__(self): return " of ".format(card_rank, card_suit) 

This uses the Python language itself to print the class and has the upside that your class will now work properly in print statements and in conversions to strings. So instead of:

Beat me by 30 sec. Even better: u’%s of %s’ % (card_rank, card_suit) (as long as you change it everywhere to card_suit ).

To expand on what shuttle87 said:

makes card_name a static variable (shared between all instances of that class)

Once you make the variable non-static (by using self.card_name in the __init__ method) you won’t have to worry about the copy part as each instance of the card class will have it’s own unique name

On that note, the deck in Deck is also static in your code.

from card import Card class Deck: # these 2 can be static, they never change between copies of the deck class card_ranks = ['ace','king','queen','jack','ten','nine','eight','seven','six','five','four','three','two'] card_suites = ['clubs','hearts','spades','diamonds'] def __init__(self): # this shouldn't be static since you might want to shuffle them # or do other things that make them unique for each deck self.cards = [] for suite in Deck.card_suites: for rank in Deck.card_ranks: self.cards.append(Card(rank, suite)) def show_deck(self): for item in self.cards: print item 
class Card: def __init__(self, rank, suite): self.rank = rank self.suite = suite def __str__(self): return self.rank + ' of ' + self.suite 
#! python2 from deck import Deck def main(): deck = Deck() deck.show_deck() if __name__ == '__main__': main() 
ace of clubs king of clubs queen of clubs jack of clubs . 

Источник

Python appending class instance to list?

I am attempting to understand how to append instances of classes to lists in Python and I think the way I am doing it is wonky. For my test code setup I am tracking an object throughout the life of the code. Let’s say this object is a man

class man_obj(): def __init__(self): self.name = "name" self.height = 0.0 self.weight = 0.0 self.action = "action" 
man_inst.name = "Adam" man_inst.height = 1.0 man_inst.weight = 1.0 man_inst.action = "looks around" 
record_man = copy.deepcopy(man_inst); man_list.append(record_man); 
man_inst.action = "exercise" man_inst.weight = 0.9 
record_man = copy.deepcopy(man_inst); man_list.append(record_man); 
import copy class man_obj(): def __init__(self): self.name = "name" self.height = 0.0 self.weight = 0.0; self.action = "action"; man_inst = man_obj(); man_inst.name = "Adam" man_inst.height = 1.0 man_inst.weight = 1.0 man_inst.action = "looks around" man_list = []; record_man = copy.deepcopy(man_inst); man_list.append(record_man); man_inst.action = "exercise" man_inst.weight = 0.9 record_man = copy.deepcopy(man_inst); man_list.append(record_man); print("name\theight\tweight\taction") for x in range(0, len(man_list)): print(man_list[x].name + "\t" + str(man_list[x].height) + "\t" + str(man_list[x].weight) + "\t"+ str(man_list[x].action)) 
name height weight action Adam 1.0 1.0 looks around Adam 1.0 0.9 exercise 

Источник

How do I append an object class to a list?

I expect to print the list of objects with respect to the if condition. I have implemented str method. Shouldn’t that be enough?

That’s what is does. It prints a list with one Person object. You see the default way Python prints objects.

BTW, that «persons» attribute should probably be called .persons , or maybe ._persons if you want to indicate that it’s a private name for use by your class’s methods and that code external to the class shouldn’t touch it directly. Names that begin with double underscores (and end with at most a single underscore) invoke Python’s name mangling machinery, and that should only be used when you really need it. And if you have to ask «Do I need name mangling here?», you probably don’t. 😉

2 Answers 2

This is just the __repr__ of the object. The __repr__ is meant to be a machine readable representation of the object and you can change it by overiding it.

list doesn’t care that your class has a __str__ method.

When you print an object, print calls str on the object to get a suitable string. The str function attempts to call the object’s __str__ method, but if it doesn’t have one then it calls the object’s __repr__ method instead. And if their isn’t a definition for __repr__ in that object’s class definition then you’ll get the one inherited from the parent class, typically that will be the default __repr__ from the base object type.

list and the other built-in collections like tuple , set and dict don’t have a __str__ method, so when you try to convert them to strings (either explicitly using the str function, or implicitly via print ) their __repr__ method is called. And those __repr__ methods in turn call repr on each item in the collection. So when you pass any of those collection objects to print you will always see the __repr__ of the items. And explictly calling str on the collection will make no difference.

If you want to see the __str__ representation of the items in a list or collection you will need to iterate over the collection, calling str explicitly on each item.

Here’s a tiny code snippet (suitable for Python 2 & 3) that illustrates these points.

from __future__ import print_function class Test(object): def __str__(self): return 'Test str' def __repr__(self): return 'Test repr' a = [Test(), Test()] print(id(a.__repr__), id(a.__str__)) print(a, str(a), repr(a)) for u in a: print(u, str(u), repr(u)) 
3075508812 3075508812 [Test repr, Test repr] [Test repr, Test repr] [Test repr, Test repr] Test str Test str Test repr Test str Test str Test repr 

So if you want to be able to print a list of your objects as a single entity and have the object’s strings be more human-friendly, you have a couple of choices:

  1. Change the name of your __str__ method to __repr__ . This is the simplest way, and as I said earlier, the __repr__ will be used if a __str__ can’t be found when the object gets passed to str .
  2. Leave the existing __str__ method alone and create a __repr__ that’s more human-friendly. However, it’s suggested that the __repr__ display useful info to a programmer who sees it, and if practical it’s nice if the __repr__ string can be copy & pasted into the interpreter or script to recreate the object.
  3. Leave the existing __str__ method alone and create a __repr__ that calls __str__ . While valid, this is a bit silly. A related strategy is to set __repr__ as a class attribute that references __str__ . See below for an example.
class Test(object): def __str__(self): return 'Test str' __repr__ = __str__ 

Источник

Оцените статью