6

I am trying to understand what's the best way to store class instances in an app, so that I access the attributes right and invoke each class method right. I would like the solution to work with ORM i.e. SqlAlchemy and add GUI in the end.

Let's say I have Notebook class. There's also Note class that can belong to one Notebook. And there's a Picture class - its instance can appear in multiple Notes that belong to different Notebook instances.

For now I thought of approach below (I've made it simpler/without ORM just to get the idea):

class Notebook(object):
    def __init__(self):
        self.notesid=[]

    def view_notes(self,notes,pictures):
        for key,item in notes.items():
            if key in self.notesid:
                item.show(pictures)

class Note(object):
    def __init__(self,id,content,picture):
        self.id = id
        self.content = content
        self.picturesid = [picture.id]
    def show(self,pictures):
        print(self.id, self.content)
        for item in pictures:
            if item.id in self.picturesid:
                print(item)

class Picture(object):
    def __init__(self,id,path):
        self.id = id
        self.path = path
    def __str__(self):
        '''shows picture'''
        return "and here's picture %s" % (self.id)

# main program

notesdict={}
pictureslist=[]

notebook1=Notebook()
picture1 = Picture('p1','path/to/file')
note1=Note('n1','hello world',picture1)

notesdict[note1.id] = note1
pictureslist.append(picture1)
notebook1.notesid.append(note1.id)

notebook1.view_notes(notesdict,pictureslist)

I am not sure if that's the proper approach as even in this simple example I need to throw all the dictionaries/instance containers into the view_notes() method. It feels like there must be a simplier/less error prone way.

All the articles I find say about class creation but I can't find anything about putting it all together in an app and "class instances management", storing multiple class instances (with both one-to-many or many-to-many links at the same time) of classes of a different kind.

Could You please direct me to proper thinking/approach either by using the code above/links to articles/books?

simplynail
  • 313
  • 1
  • 4
  • 13
  • Could you correct the subject line to match the text? Are you storing classes or instances (objects)? The distinction matters. And what do you mean by an `app`? In other words, in what kind of environment, or OS, are running this code? – hpaulj Jan 11 '16 at 01:15
  • I have changed the subject as suggested. Not sure how the second question matters, but for the 'app' I mean main loop, I will be running it on Windows(but if it is Python interpreter I guess the os doesn't matter?) – simplynail Jan 11 '16 at 07:25
  • OK, what do you mean by 'store'? Is the focus on data structures while the 'app' is running, or storing objects longterm (in a file or database)? In Python lists and dictionaries are the normal structures for collecting objects – hpaulj Jan 11 '16 at 17:20
  • Ok, lets start with non-persistant storing. Where this dictionary/should be created (based on my example)? In the main loop? I don't feel it's a good idea because I would need to pass more and more lists to the methods. Is it how it should be done? I read somewhere that this list can be created inside class, ie here in Notebook class I would create self.notes list/dict if I understand it right. Which approach is better? Or is there another one? – simplynail Jan 11 '16 at 23:24
  • If logically a `Notebook` contains `Notes`, then I'd give it an attribute (list or dict) that can contain `Note` objects, not just their ids. And the `Notebook` `__init__` might accept a list of `Notes`. A `Note` object can be in several collections at once, whether it's a global list, or one of several `Notebook`s. – hpaulj Jan 12 '16 at 00:45
  • Can You explain more the last sentence about instance related to multiple Notebooks? How to store the Note objects then? – simplynail Jan 12 '16 at 10:01

1 Answers1

3

OK, I understood it. Class instances can be stored in attributes of list/dictionary type in other class instances (eg Note instance inside Notebook instance).

The important thing to remember is what actually gets stored inside that attribute is reference to the instance located under certain address in the RAM memory, not the instance directly.

Consider this:

class Notebook(object):    
     def __init__(self, iteminstance):
        self.lista = [iteminstance]
     def show(self):
        print('Container1 list:')
        for item in self.lista:
            print(item.content)

class Binder(object):    
     def __init__(self, iteminstance):
        self.lista = [iteminstance]
     def show(self):
        print('Container2 list:')
        for item in self.lista:
            print(item.content)

class Note(object):    
    def __init__(self, txt):    
        self.content = txt    

# create Notebook instance and store Note instance in 'lista' list argument    
a=Notebook(Note(5))    
a.show()    

# assign the same Note instance to different container, Binder instance    
b=Binder(a.lista[0])    
b.show()

# check if both containers include the same object    
print(a.lista==b.lista)
>>>True

# change content of the Note instance via Notebook instance    
a.lista[0].content = 10

# check if content has changed in both Notebook and Binder instances 
a.show()    
b.show()

So after second assignment (to the Binder) what gets copied is actually just the reference to the memory address.

So every change in the stored object (in Note in this case) is accessible via every Container. I thought that second assignment would copy the instance at its current state - but it doesn't.

Thanks hpaulj for asking the right questions! For further reading I need to look up 'collection class' I think.

simplynail
  • 313
  • 1
  • 4
  • 13