finding the parent class (not superclass) of the currently executingmethod derived from a Borg class

Discussion in 'Python' started by seanacais, Sep 8, 2008.

  1. seanacais

    seanacais Guest

    I want to create a class derived from a Borg class that can
    instantiated as part of a script or be contained in other classes.
    When methods from the Borg class are called, I would like to know the
    name of the class that contains the Borg class.

    I've played a bit with inspect and _getframe from the sys module but
    get inconsistent results. The main problem is if the Borg class is
    instantiated outside a containing class, then I need to go up a
    different number of stack frames. But this information isn't
    available till after I've run out of stack frames.

    Hopefully the following code better describes what I'm looking to do.

    import sys

    class Borg:
    _shared_state = {}
    def __init__(self):
    self.__dict__=self._shared_state

    class Assimilated(Borg):
    valueByCaller = {}

    def __init__(self, setupvalue):
    print "In Assimilated.__init__()"
    print "setupvalue is: " + str(setupvalue)

    # would like key to be name of class (or module) that
    # contins Assimilated
    callerID = sys._getframe(1).f_code.co_name

    self.valueByCaller[callerID] = setupvalue

    print self.valueByCaller

    def action(self, calledvalue):
    print "In Assimilated.action()"
    print "self.__classname__: " + self.__class__.__name__
    print "calledvalue is: " + str(calledvalue)

    print "self.valueByCaller"
    print self.valueByCaller

    # need to get proper key depending on which class (or module)
    # made the call
    # print "0: " + sys._getframe(0).f_code.co_name
    # print "1: " + sys._getframe(1).f_code.co_name
    # print "2: " + sys._getframe(2).f_code.co_name
    # print "3: " + sys._getframe(3).f_code.co_name
    callerID = sys._getframe(2).f_code.co_name
    print "callerID"
    print callerID

    if(self.valueByCaller[callerID] <= calledvalue):
    print "doing the action"


    class A:
    assim_object = Assimilated(2)

    def __init__(self):
    self.assim_object.action(2)
    self.assim_object.action(3)

    class B:
    assim_object = Assimilated(3)

    def __init__(self):
    self.assim_object.action(3)
    self.assim_object.action(4)

    class C:
    assim_object = Assimilated(4)

    def __init__(self):
    self.assim_object.action(4)
    self.assim_object.action(5)


    a=A()
    b=B()
    c=C()

    obj=Assimilated(3)
    #obj.action(3)


    When I run this, I get the following output:

    In Assimilated.__init__()
    setupvalue is: 2
    {'A': 2}
    In Assimilated.__init__()
    setupvalue is: 3
    {'A': 2, 'B': 3}
    In Assimilated.__init__()
    setupvalue is: 4
    {'A': 2, 'C': 4, 'B': 3}
    In Assimilated.action()
    self.__classname__: Assimilated
    calledvalue is: 2
    self.valueByCaller
    {'A': 2, 'C': 4, 'B': 3}
    callerID
    <module>
    Traceback (most recent call last):
    File "\CallerID.py", line 67, in <module>
    a=A()
    File "\CallerID.py", line 49, in __init__
    self.assim_object.action(2)
    File "\CallerID.py", line 41, in action
    if(self.valueByCaller[callerID] <= calledvalue):
    KeyError: '<module>'

    What I found most peculiar when I started this was that the
    valueByCaller dictionary was completely populated before the __init__
    method of a was executed. I'm pretty sure that this has to do with
    the difference between when the object gets instanced and when it gets
    initialized, but I need to do some more research and reading to be
    able to explain it to myself.

    Thanks for any help you can give me.

    Kevin
     
    seanacais, Sep 8, 2008
    #1
    1. Advertising

  2. seanacais a écrit :
    > I want to create a class derived from a Borg class that can
    > instantiated as part of a script or be contained in other classes.
    > When methods from the Borg class are called, I would like to know the
    > name of the class that contains the Borg class.



    > I've played a bit with inspect and _getframe from the sys module but
    > get inconsistent results. The main problem is if the Borg class is
    > instantiated outside a containing class, then I need to go up a
    > different number of stack frames. But this information isn't
    > available till after I've run out of stack frames.


    The simplest solution is usually the better : explicitely pass the
    caller (whether instance or module or whatever you want)


    > Hopefully the following code better describes what I'm looking to do.
    >
    > import sys
    >
    > class Borg:
    > _shared_state = {}
    > def __init__(self):
    > self.__dict__=self._shared_state
    >
    > class Assimilated(Borg):
    > valueByCaller = {}


    You understand that, being a class attribute, valueByCaller won't be
    part of the Borg's _shared_state ?

    > def __init__(self, setupvalue):
    > print "In Assimilated.__init__()"
    > print "setupvalue is: " + str(setupvalue)
    >
    > # would like key to be name of class (or module) that
    > # contins Assimilated
    > callerID = sys._getframe(1).f_code.co_name
    >
    > self.valueByCaller[callerID] = setupvalue
    >
    > print self.valueByCaller


    Anyway, since you override __init__ and don't call Borg.__init__, your
    Assimilated class doesn't behave as a Borg.

    (snip)


    >
    > When I run this, I get the following output:
    >
    > In Assimilated.__init__()
    > setupvalue is: 2
    > {'A': 2}
    > In Assimilated.__init__()
    > setupvalue is: 3
    > {'A': 2, 'B': 3}
    > In Assimilated.__init__()
    > setupvalue is: 4
    > {'A': 2, 'C': 4, 'B': 3}
    >

    (snip)
    >
    > What I found most peculiar when I started this was that the
    > valueByCaller dictionary was completely populated before the __init__
    > method of a was executed.


    Indeed. In classes A, B and C, assim_object is class attribute - so it
    is instanciated when the class statement is executed.

    > I'm pretty sure that this has to do with
    > the difference between when the object gets instanced and when it gets
    > initialized,


    Not at all. It has to do with the fact that all statements within a
    class block are executed before the class statement itself is executed.
    And since your class statements are at the top-level, they are executed
    when the module is initialised (that is, passed to the python runtime or
    first imported).

    > but I need to do some more research and reading to be
    > able to explain it to myself.


    Indeed. May I suggest that you *learn* Python's object model and
    Python's execution model instead of assuming anything ? This will save
    you a whole lot of time and frustration !-)
     
    Bruno Desthuilliers, Sep 9, 2008
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    1
    Views:
    396
    myork
    May 23, 2007
  2. Replies:
    1
    Views:
    389
    Victor Bazarov
    May 23, 2007
  3. Evan Klitzke
    Replies:
    0
    Views:
    367
    Evan Klitzke
    Aug 2, 2007
  4. bart van deenen
    Replies:
    6
    Views:
    760
    bart van deenen
    Mar 3, 2009
  5. Chris Roos
    Replies:
    7
    Views:
    119
Loading...

Share This Page