Object instance "reporting" to a container class instance

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Daniel Lipovetsky

    #1

    Object instance "reporting" to a container class instance

    I would like for an object to "report" to a container object when a
    new instance is created or deleted. I could have a container object
    that is called when a new instance is created, as below.

    class AnyObject:
    pass

    class Container:
    links = []
    def add(self,other) :
    while other not in self.links:
    self.links.appe nd(other)
    def rem(self,other) :
    while other in self.links:
    self.links.remo ve(other)
    ....

    container = Container()
    a = AnyObject()
    container.add(a )

    My question is: can (should? :-) this "reporting" be done inside the
    instance's __init__ and __del__ methods (that is, an instance
    "reports" to the container as soon as it is created or deleted)?

    Thanks!
    Daniel

    ---

    I'm working out a design where Object A is "linked" to Object B, and
    both objects become aware of that relationship. I have implemented an
    example successfully; the code is below. My main question is above,
    but I would appreciate comments on the code! (For example, I'm
    wondering whether my way of defining variables in the class but
    assigning them locally to each instance (in the "Object.ini t" method)
    is really a bad kludge...)


    class Object():
    def __del__(self):
    print "buh-bye!", self # Verbose for understanding garbage cleanup
    def init(self,name) :
    self.links = []
    self.name = name
    def add(self,other) :
    while other not in self.links:
    self.links.appe nd(other)
    other.add(self)
    def rem(self,other) :
    while other in self.links:
    self.links.remo ve(other)
    other.rem(self)

    class Student(Object) :
    def __init__(self,n ame):
    self.init(name)

    class Section(Object) :
    def __init__(self,n ame):
    self.init(name)

    class Task(Object):
    def __init__(self,n ame):
    self.init(name)

    ## Construct test instances!

    students = {}
    for name in ['Jose','Daniel' ,'Rusty']:
    student = Student(name)
    students[name] = student

    sections = {}
    for name in ['English 1']:
    section = Section(name)
    sections[name] = section

    tasks = {}
    for name in ['Homework 1','Exam 1','Homework 2','Exam 2']:
    task = Task(name)
    tasks[name] = task

    # Display example connections
    def show_connection s():
    for section in sections:
    print sections[section].name
    for link in sections[section].links:
    print "\t", link.name

    # Add some connections...

    print "Now adding connections..."
    for name in tasks:
    sections['English 1'].add(tasks[name])
    show_connection s()

    # Remove some connections...

    print "Now removing connections..."
    for name in tasks:
    sections['English 1'].rem(tasks[name])
    show_connection s()

    for task in tasks:
    print tasks[task].links

    for section in sections:
    print sections[section].links

    ## Test garbage cleanup

    sections['English 1'].add(tasks['Exam 1'])
    print sections['English 1'].links
    sections['English 1'].rem(tasks['Exam 1'])
    del sections['English 1']
  • Alex Martelli

    #2
    Re: Object instance "reporting " to a container class instance

    Daniel Lipovetsky <daniel.lipovet sky@gmail.comwr ote:
    I would like for an object to "report" to a container object when a
    new instance is created or deleted. I could have a container object
    that is called when a new instance is created, as below.
    >
    class AnyObject:
    pass
    >
    class Container:
    links = []
    Why a class variable rather than a normal instance variable?
    def add(self,other) :
    while other not in self.links:
    self.links.appe nd(other)
    What a weird implementation. .. why the while, &c?!
    def rem(self,other) :
    while other in self.links:
    self.links.remo ve(other)
    Ditto.
    ...
    >
    container = Container()
    a = AnyObject()
    container.add(a )
    >
    My question is: can (should? :-) this "reporting" be done inside the
    instance's __init__ and __del__ methods (that is, an instance
    "reports" to the container as soon as it is created or deleted)?
    The object's __del__ will never be called, because the object's presence
    in the Container's self.links will always keep the object alive.

    Study weak references -- and make the Container's links (whether it
    needs to be a class or instance variable for the container) a
    weakref.WeakVal ueDictionary (as keys, use unique, always-incrementing
    integers) -- a WeakKeyDictiona ry is OK too if contained objects are
    hashable by identity (and might make other things easier, e.g. moving an
    object from one container to another by removing it from one and adding
    it from the other).

    With weak references, the "reporting" of the object's demise will be
    automatic and transparent - the relevant dict entry just disappears when
    the object does. For the "registrati on", the call to the add method of
    the container, it's fine to do it in __init__ if at contained-object's
    init time you already know, invariably, what container it will be in.


    Alex

    Comment

    • Jordan Greenberg

      #3
      Re: Object instance &quot;reporting &quot; to a container class instance

      Daniel Lipovetsky wrote:
      I would like for an object to "report" to a container object when a
      new instance is created or deleted. I could have a container object
      that is called when a new instance is created, as below.
      I've run into a similar problem before, in my case it was easiest to
      allow the container to create the new instances, sort of like:

      <CODE>

      class Something(objec t):
      def __init__(self, *args):
      self.x=args

      class Container(objec t):
      def __init__(self):
      self.instances=[]

      def newinstance(sel f, newclass, *args):
      tmp=newclass(ar gs)
      self.instances. append(tmp)
      return tmp

      def delinstance(sel f, inst):
      self.instances. remove(inst)
      cont=Container( )
      a=cont.newinsta nce(Something, 5, 6)
      b=cont.newinsta nce(Something, 7, 8)
      c=cont.newinsta nce(Something, 8, 9)

      print len(cont.instan ces)

      cont.delinstanc e(b)
      print len(cont.instan ces)

      #note that b is still defined, unless you remove that name explicitly...
      print b
      del b
      print b

      </CODE>

      This can be very, very, very ugly. I don't particularly actually
      recommend doing anything like this. Usually you should re-think your
      organization to make this unnecessary. I suppose, though, it can come in
      handy in certain situations.

      -Jordan G

      Comment

      Working...