Keeping track of subclasses and instances?

Discussion in 'Python' started by Karlo Lozovina, Oct 11, 2007.

  1. Hi,

    what's the best way to keep track of user-made subclasses, and instances of
    those subclasses? I just need a pointer in a right direction... thanks.

    --
    Karlo Lozovina -- Mosor
     
    Karlo Lozovina, Oct 11, 2007
    #1
    1. Advertising

  2. Karlo Lozovina

    Larry Bates Guest

    Karlo Lozovina wrote:
    > Hi,
    >
    > what's the best way to keep track of user-made subclasses, and instances of
    > those subclasses? I just need a pointer in a right direction... thanks.
    >

    I'm not completely sure I understand the question but here goes. Instances of
    classes are classes can be stored in lists or dictionaries. In lists you
    reference them via their index (or iterate over them) and in dictionaries you
    can give them a name that is used as a key.

    Hope this helps.

    -Larry
     
    Larry Bates, Oct 11, 2007
    #2
    1. Advertising

  3. Larry Bates wrote:

    > I'm not completely sure I understand the question but here goes.
    > Instances of
    > classes are classes can be stored in lists or dictionaries. In lists you
    > reference them via their index (or iterate over them) and in dictionaries
    > you can give them a name that is used as a key.


    I wish if it were that simple :).

    Here is a longer description - I have a function that given input creates a
    custom class and returns it back. The user is free to subclass that (even
    more, he should do that), and of course he will make instances of those
    subclasses. Now, my question is how to keep track of subclasses and their
    instances, without the need for user interaction (appending them to a list,
    or adding to dictionary)?

    Thanks,

    --
    Karlo Lozovina - Mosor
     
    Karlo Lozovina, Oct 11, 2007
    #3
  4. On Oct 10, 9:19 pm, Karlo Lozovina <> wrote:
    > Larry Bates wrote:
    > > I'm not completely sure I understand the question but here goes.
    > > Instances of
    > > classes are classes can be stored in lists or dictionaries. In lists you
    > > reference them via their index (or iterate over them) and in dictionaries
    > > you can give them a name that is used as a key.

    >
    > I wish if it were that simple :).
    >
    > Here is a longer description - I have a function that given input creates a
    > custom class and returns it back. The user is free to subclass that (even
    > more, he should do that), and of course he will make instances of those
    > subclasses. Now, my question is how to keep track of subclasses and their
    > instances, without the need for user interaction (appending them to a list,
    > or adding to dictionary)?
    >
    > Thanks,
    >
    > --
    > Karlo Lozovina - Mosor



    I guess Larry's actual question was why do *you* need to keep track of
    users' instances and subclasses and don't let them keep track on their
    own if/when they need it. I realize there are legitimate use cases for
    this but it's not typical. Anyway, here's something to get you
    started; all a user has to do is derive (directly or indirectly) from
    InstanceTracker and, if a class C defines __init__,
    super(C,self).__init__() should be called explicitly:


    from collections import deque
    from weakref import WeakKeyDictionary

    class InstanceTracker(object):
    def __init__(self):
    try: all = self.__class__.__dict__['__instances__']
    except KeyError:
    self.__class__.__instances__ = all = WeakKeyDictionary()
    all[self] = None

    def iter_instances(cls):
    return iter(cls.__dict__.get('__instances__',[]))

    def iter_descendant_classes(cls):
    memo = set()
    unvisited = deque(cls.__subclasses__())
    while unvisited:
    top = unvisited.popleft()
    if top not in memo:
    memo.add(top); yield top
    unvisited.extend(top.__subclasses__())

    #----- example --------------------------------------
    if __name__ == '__main__':

    class A(InstanceTracker): pass
    class B1(A): pass
    class B2(A): pass
    class C1(B1,B2):
    def __init__(self):
    super(C1,self).__init__()
    class C2(B1,B2): pass
    class D(C1,C2): pass

    items = [A(),B1(),B2(),C1(),C1(),D(),A(),B2()]
    print ' * Instances per class'
    for c in iter_descendant_classes(A):
    print c, list(iter_instances(c))

    print ' * Instances per class (after delete)'
    del items
    for c in iter_descendant_classes(A):
    print c, list(iter_instances(c))


    HTH,
    George
     
    George Sakkis, Oct 11, 2007
    #4
  5. On Thu, 11 Oct 2007 03:19:07 +0200, Karlo Lozovina wrote:

    > Here is a longer description - I have a function that given input
    > creates a custom class and returns it back. The user is free to subclass
    > that (even more, he should do that), and of course he will make
    > instances of those subclasses. Now, my question is how to keep track of
    > subclasses and their instances, without the need for user interaction
    > (appending them to a list, or adding to dictionary)?


    The real question is why you think you need to keep track of them instead
    of letting the user and/or Python keep track of them, like any other
    object.


    --
    Steven.
     
    Steven D'Aprano, Oct 11, 2007
    #5
  6. On Oct 10, 8:17 pm, Karlo Lozovina <> wrote:
    > Hi,
    >
    > what's the best way to keep track of user-made subclasses, and instances of
    > those subclasses? I just need a pointer in a right direction... thanks.
    >
    > --
    > Karlo Lozovina -- Mosor


    This recipe does what you want, with the intent of providing
    automatic finalization of the instances, but you should be able
    to tweak it to do everything you wish:

    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/523007

    Michele Simionato
     
    Michele Simionato, Oct 11, 2007
    #6
  7. On Wed, 10 Oct 2007 21:35:44 -0700, Michele Simionato wrote:

    > On Oct 10, 8:17 pm, Karlo Lozovina <> wrote:
    >> Hi,
    >>
    >> what's the best way to keep track of user-made subclasses, and
    >> instances of those subclasses? I just need a pointer in a right
    >> direction... thanks.
    >>
    >> --
    >> Karlo Lozovina -- Mosor

    >
    > This recipe does what you want, with the intent of providing automatic
    > finalization of the instances, but you should be able to tweak it to do
    > everything you wish:
    >
    > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/523007



    Well, that answers my earlier question about why you might want to track
    instances. But it seems like an unnecessarily complicated way of doing it.

    From your recipe:

    [module deallocating.py]

    import logging

    class C(object):
    def __init__(self):
    logging.warn('Allocating resource ...')
    def __del__(self):
    logging.warn('De-allocating resource ...')
    print 'THIS IS NEVER REACHED!'

    if __name__ == '__main__':
    c = C()


    Is there a problem with writing C like this?

    class C(object):
    def __init__(self):
    logging.warn('Allocating resource ...')
    self.__log = logging.warn
    def __del__(self):
    self.__log('De-allocating resource ...')
    print 'THIS IS REACHED!'



    It works for me. Have I missed something?


    --
    Steven.
     
    Steven D'Aprano, Oct 11, 2007
    #7
  8. On Oct 10, 6:19 pm, Karlo Lozovina <> wrote:
    > Larry Bates wrote:
    > > I'm not completely sure I understand the question but here goes.
    > > Instances of
    > > classes are classes can be stored in lists or dictionaries. In lists you
    > > reference them via their index (or iterate over them) and in dictionaries
    > > you can give them a name that is used as a key.

    >
    > I wish if it were that simple :).
    >
    > Here is a longer description - I have a function that given input creates a
    > custom class and returns it back. The user is free to subclass that (even
    > more, he should do that), and of course he will make instances of those
    > subclasses. Now, my question is how to keep track of subclasses and their
    > instances, without the need for user interaction (appending them to a list,
    > or adding to dictionary)?
    >
    > Thanks,
    >
    > --
    > Karlo Lozovina - Mosorclass Meta(type):


    What about the following solution?

    class Meta(type):
    def __new__(mcl,*args,**kw):
    class_ = super(Meta,mcl).__new__(mcl,*args,**kw)
    mcl._classes.append(class_)
    class_._instances = []
    return class_
    _classes = []

    def factory():
    class Class(object):
    __metaclass__ = Meta
    def __new__(cls,*args,**kw):
    instance = super(Class,cls).__new__(cls,*args,**kw)
    cls._instances.append(instance)
    return instance
    return Class

    >>> A = factory()
    >>> class B(A): pass

    ....
    >>> a = A()
    >>> b = B()
    >>> Meta._classes

    [<class 'meta.Class'>, <class '__main__.B'>]
    >>> A._instances

    [<meta.Class object at 0xb7dbb08c>]
    >>> B._instances

    [<__main__.B object at 0xb7dbb0ec>]

    So, you see that you can access all classes, their subclasses, and
    instances from Meta.

    Of course in a more elaborate version _classes and _instances should
    store weak references, so that classes and instances can actually be
    deleted. I also haven't explored under which circumstances this can
    break ...

    I can imagine different use cases for this, (though they certainly are
    non-standard :)). I once contemplated the (toy-) implementation of a
    frame-based knowledge representation system using Python's object
    model, where one definitely needs classes to keep track of their
    instances ...

    Cheers,
    Andreas
     
    Andreas Kraemer, Oct 11, 2007
    #8
  9. Karlo Lozovina schrieb:
    > Hi,
    >
    > what's the best way to keep track of user-made subclasses, and instances of
    > those subclasses? I just need a pointer in a right direction... thanks.
    >


    New style classes have a __subclasses__ class method that shows the direct subclasses:

    Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> object.__subclasses__()

    [<type 'type'>, <type 'weakref'>, <type 'int'>, <type 'basestring'>, <type 'list'>, <type 'NoneType'>, ...
    >>>


    No builtin mechanism for instances exists, afaik.

    Thomas
     
    Thomas Heller, Oct 11, 2007
    #9
  10. Karlo Lozovina

    Paul Rubin Guest

    Steven D'Aprano <> writes:
    > Is there a problem with writing C like this?
    > class C(object):
    > def __init__(self):
    > logging.warn('Allocating resource ...')
    > self.__log = logging.warn


    > It works for me. Have I missed something?


    I thought the OP wanted to the program to notice when subclasses were
    created, not just instances of them. As Andreas Kraemer described,
    you can do that with a metaclass.
     
    Paul Rubin, Oct 11, 2007
    #10
  11. On Oct 11, 7:16 am, Steven D'Aprano <st...@REMOVE-THIS-
    cybersource.com.au> wrote:
    > Is there a problem with writing C like this?
    >
    > class C(object):
    > def __init__(self):
    > logging.warn('Allocating resource ...')
    > self.__log = logging.warn
    > def __del__(self):
    > self.__log('De-allocating resource ...')
    > print 'THIS IS REACHED!'
    >
    > It works for me. Have I missed something?


    Another more common workaround is to use default arguments:

    class C(object):
    def __init__(self):
    logging.warn('Allocating resource ...')
    def __del__(self, warn=logging.warn):
    warn('De-allocating resource ...')
    print 'THIS IS REACHED!'

    But, as you know, I want to remove __del__ because of the problem with
    reference
    cycles, not because of this little issue with the cleanup mechanism
    (which BTW is shared
    also by the weak references callback mechanism).

    Michele Simionato
     
    Michele Simionato, Oct 11, 2007
    #11
  12. Karlo Lozovina

    Erik Jones Guest

    On Oct 11, 2007, at 12:49 AM, Andreas Kraemer wrote:

    > On Oct 10, 6:19 pm, Karlo Lozovina <> wrote:
    >> Larry Bates wrote:
    >>> I'm not completely sure I understand the question but here goes.
    >>> Instances of
    >>> classes are classes can be stored in lists or dictionaries. In
    >>> lists you
    >>> reference them via their index (or iterate over them) and in
    >>> dictionaries
    >>> you can give them a name that is used as a key.

    >>
    >> I wish if it were that simple :).
    >>
    >> Here is a longer description - I have a function that given input
    >> creates a
    >> custom class and returns it back. The user is free to subclass
    >> that (even
    >> more, he should do that), and of course he will make instances of
    >> those
    >> subclasses. Now, my question is how to keep track of subclasses
    >> and their
    >> instances, without the need for user interaction (appending them
    >> to a list,
    >> or adding to dictionary)?
    >>
    >> Thanks,
    >>
    >> --
    >> Karlo Lozovina - Mosorclass Meta(type):

    >
    > What about the following solution?
    >
    > class Meta(type):
    > def __new__(mcl,*args,**kw):
    > class_ = super(Meta,mcl).__new__(mcl,*args,**kw)
    > mcl._classes.append(class_)
    > class_._instances = []
    > return class_
    > _classes = []
    >
    > def factory():
    > class Class(object):
    > __metaclass__ = Meta
    > def __new__(cls,*args,**kw):
    > instance = super(Class,cls).__new__(cls,*args,**kw)
    > cls._instances.append(instance)
    > return instance
    > return Class
    >
    >>>> A = factory()
    >>>> class B(A): pass

    > ...
    >>>> a = A()
    >>>> b = B()
    >>>> Meta._classes

    > [<class 'meta.Class'>, <class '__main__.B'>]
    >>>> A._instances

    > [<meta.Class object at 0xb7dbb08c>]
    >>>> B._instances

    > [<__main__.B object at 0xb7dbb0ec>]
    >
    > So, you see that you can access all classes, their subclasses, and
    > instances from Meta.
    >
    > Of course in a more elaborate version _classes and _instances should
    > store weak references, so that classes and instances can actually be
    > deleted. I also haven't explored under which circumstances this can
    > break ...
    >
    > I can imagine different use cases for this, (though they certainly are
    > non-standard :)). I once contemplated the (toy-) implementation of a
    > frame-based knowledge representation system using Python's object
    > model, where one definitely needs classes to keep track of their
    > instances ...


    Another use case that I've run across is when defining model classes
    using an ORM against a database that uses table inheritance
    extensively with the result that the database has way more tables
    than you'd actually want to manually maintain model classes/files for.

    Erik Jones

    Software Developer | Emma®

    800.595.4401 or 615.292.5888
    615.292.0777 (fax)

    Emma helps organizations everywhere communicate & market in style.
    Visit us online at http://www.myemma.com
     
    Erik Jones, Oct 11, 2007
    #12
  13. George Sakkis a écrit :
    (snip)

    > Anyway, here's something to get you
    > started; all a user has to do is derive (directly or indirectly) from
    > InstanceTracker and, if a class C defines __init__,
    > super(C,self).__init__() should be called explicitly:


    Actually, you don't even need that restriction - just move the tracking
    code from __init__ to __new__.

    >
    > from collections import deque
    > from weakref import WeakKeyDictionary
    >
    > class InstanceTracker(object):

    def __new__(cls, *args, **kw):
    try:
    all = cls.__dict__['__instances__']
    except KeyError:
    cls.__instances__ = all = WeakKeyDictionary()
    self = super(InstanceTracker, self).__new__(cls)
    all[self] = None
    return self

    (NB : untested)
     
    Bruno Desthuilliers, Oct 11, 2007
    #13
    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. John
    Replies:
    0
    Views:
    369
  2. Utter Newbie
    Replies:
    0
    Views:
    478
    Utter Newbie
    Jul 28, 2003
  3. Manuel
    Replies:
    1
    Views:
    359
    John Saunders
    Dec 11, 2004
  4. Klaus Jensen
    Replies:
    0
    Views:
    303
    Klaus Jensen
    May 29, 2007
  5. Joe Van Dyk
    Replies:
    3
    Views:
    228
    Ara.T.Howard
    Jun 25, 2005
Loading...

Share This Page