Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Basic Object-Oriented Python Emulating Built-ins __iter__

Guillaume Crt
Guillaume Crt
6,395 Points

using __init__ method instead of class attribute in this example ?

in the example this code is used :

{
class Bookcase:
   def __init__(self):
       self.books = []
}

but I think writing that is more logical :

{
class Bookcase:
    books = []
}

Am I wrong ? Is there any major difference ? Thanks

2 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,457 Points

Great question @Guilla Guillaume Crt!! The issue is that the attribute books is a mutable list.

As a class variable, each instance would be operating on the same list. If created in the __init__ method, the books list would be local to each instance and independent of the other instances.

Look at the following code to see this in action:

$ python
Python 3.8.5 (default, Jul 28 2020, 12:59:40) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class Bookcase1:
...     def __init__(self):
...         self.books = []
... 
>>> class Bookcase2:
...     books = []
... 
# playing with instances using __init__
>>> bc1a = Bookcase1()
>>> bc1a.books
[]
>>> bc1a.books.append('Title 1a')
>>> bc1a.books
['Title 1a']
>>> bc1b = Bookcase1()
>>> bc1b.books
[]
>>> bc1b.books.append('Title 1b')
>>> bc1b.books
['Title 1b']
>>> bc1a.books
['Title 1a']
# playing with instances using class attribute
>>> bc2a = Bookcase2()
>>> bc2a.books
[]
>>> bc2a.books.append('Title 2a')
>>> bc2a.books
['Title 2a']
>>> bc2b = Bookcase2()
# notice the second instance is operating on the same list
>>> bc2b.books
['Title 2a']
>>> bc2b.books.append('TItle 2b')
>>> bc2b.books
['Title 2a', 'TItle 2b']
>>> bc2a.books
['Title 2a', 'TItle 2b']
# They are literally the same object.
>>> bc2a.books is bc2b.books
True

Going beyond your question, if using a class attribute, a local attribute can be forced:

>>> bc2b.books = []
# bc2b.books is now local
>>> bc2b.books
[]
>>> bc2b.books.append('New Title 2b')
>>> bc2b.books
['New Title 2b']
>>> bc2a.books
['Title 2a', 'TItle 2b']
# bc2a still using class attribute
# if local bc2b.books is deleted, 
# the attribute reference reverts to class attribute
>>> del bc2b.books
>>> bc2b.books
['Title 2a', 'TItle 2b']

Post back if you need more help. Good Luck!!

Guillaume Crt
Guillaume Crt
6,395 Points

I get it , thank you very much !