5

If I try to print the class variable which is a list, I get a Python object. (These are examples I found on stackoverflow).

 class Contacts:
    all_contacts = []

    def __init__(self, name, email):
       self.name = name
       self.email = email
       Contacts.all_contacts.append(self)

    def __str__(self):
       return '%s, <%s>' % (self.name, self.email)

c1 = Contacts("Grace", "something@hotmail.com")
print(c1.all_contacts)

[<__main__.Contact object at 0x0287E430>, <__main__.Contact object`

But in this more simple example, it actually prints:

class Example():
    samplelist= [1,2,3]

test= Example()
print (test.samplelist)
[1, 2, 3]

I figured this line is the culprit: Contact.all_contacts.append(self) in the first sample code. But I'm not exactly sure whats going on here.

EDIT:

Several users told me to just append self.name instead of just self.

So when I do this:

class Contacts:
   all_contacts = []

   def __init__(self, name, email):
      self.name = name
      self.email = email
      Contacts.all_contacts.append(self.name)
      Contacts.all_contacts.append(self.email)

   def __str__(self):
      return '%s, <%s>' % (self.name, self.email)

   def __repr__(self):
      return str(self)

c1 = Contacts("Paul", "something@hotmail.com")
c2 = Contacts("Darren", "another_thing@hotmail.com")
c3 = Contacts("Jennie", "different@hotmail.com")

print(Contacts.all_contacts)

I get:

['Paul', 'something@hotmail.com', 'Darren', 'another_thing@hotmail.com', 'Jennie', 'different@hotmail.com']

Instead of:

[Paul, <something@hotmail.com>, Darren, <another_thing@hotmail.com>, Jennie, <different@hotmail.com>]

Thus, the formatting in the __str__ method isn't working here.

dyao
  • 983
  • 3
  • 12
  • 25
  • 1
    why don't you do : `Contacts.all_contacts.append(self.name)` – Harsh Vardhan Ladha Oct 01 '15 at 07:25
  • That would only append the name to the list. – dyao Oct 01 '15 at 07:28
  • 1
    will it be harm if you can paste actual code. I can see your class name as `Contacts` and you're instantiating `Contact` class. `c1` variable doesn't even exist and you're printing it. how? – Harsh Vardhan Ladha Oct 01 '15 at 07:32
  • 2
    Using `Contacts.all_contacts.append(self)` passes `contact1` into your list. If you want to append the contact name, you'd have to pass `self.name`, or whatever attribute you want. By passing in `contact1`, you are passing in a reference to the instance of `Contact` that you created. – dbishop Oct 01 '15 at 07:33
  • @Harsh Vardhan Ladha, I see the problem. I made a typo there. – dyao Oct 01 '15 at 07:35
  • in `__init__` do `self.all_contacts.append(name)`. No need to use the class name – Pynchia Oct 01 '15 at 07:38

3 Answers3

13

When you print a list, it calls the __str__ for the list, but list internally calls __repr__() for its element. You should implement the __repr__() for your class as well. Example -

class Contacts:
    all_contacts = []

    def __init__(self, name, email):
       self.name = name
       self.email = email
       Contacts.all_contacts.append(self)

    def __str__(self):
       return '%s, <%s>' % (self.name, self.email)

    def __repr__(self):
        return str(self)

Demo -

class Contacts:
    all_contacts = []

    def __init__(self, name, email):
       self.name = name
       self.email = email
       Contacts.all_contacts.append(self)

    def __str__(self):
       return '%s, <%s>' % (self.name, self.email)

    def __repr__(self):
        return str(self)

contact1 = Contacts("Grace1", "something1@hotmail.com")
contact2 = Contacts("Grace2", "something2@hotmail.com")
contact3 = Contacts("Grace3", "something3@hotmail.com")
print(Contacts.all_contacts)

Result -

[Grace1, <something1@hotmail.com>, Grace2, <something2@hotmail.com>, Grace3, <something3@hotmail.com>]

Also, from the output it would seem like the list actually has 6 elements, so you should consider changing that the __repr__ returns.

Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
  • 2
    FYI, `__str__` defaults to `__repr__` if no implementation is provided. So you only need to define `__repr__`. – Dunes Oct 01 '15 at 07:46
  • I guess the problem with some of the solutions telling me to pass `self.name` instead is that the formatting in `__str__` method is bypassed. Is there a reason for this? – dyao Oct 01 '15 at 07:57
  • Isn't the real question: what information do you need on the all_contacts list? Decide that, then figure out how to print it. – DisappointedByUnaccountableMod Oct 01 '15 at 08:09
  • @bLunt Can you clarify what you mean? Like I said when printing list, `str()` on list is called, but `list` internally calls `repr()` on its elements, when you do not provide an `__repr__()` , for the element of the list, it uses the `__repr__()` from `object` class, which si what you see in your output. Does that answer your question? – Anand S Kumar Oct 01 '15 at 08:35
  • @Anand S Kumar, I apologize, should I clarify in the original post or should I remake a new question? – dyao Oct 01 '15 at 14:35
  • Apologize for what? You can ask for clarifications here. What don't you understand? – Anand S Kumar Oct 01 '15 at 14:36
  • WHY are you doing WHAT several users told you to do? Check my answer out? It has what you want. – Anand S Kumar Oct 02 '15 at 05:00
  • 1
    when you add `self.name` you add the variable into the list, not the object itself, you simply add the string `self.name` and `self.email` , not the object, so yes the object's `__str__` or `__repr__` will not be claled. – Anand S Kumar Oct 02 '15 at 05:01
  • Thanks for the reminder. Bingo, that answer clarified it. Thanks again! – dyao Oct 02 '15 at 05:04
3

Your code constructs a list of objects when it says:

Contacts.all_contacts.append(self)

because self is an object, and gets appended to the all_contacts list..

If you want something different, append something different to the all_contacts list.

2

python will call str for list object (all_contacts) only, not for every item in the list.

For built-in types python is able to print the value.

Shan
  • 964
  • 9
  • 11