Access descendant class's module namespace from superclass

Discussion in 'Python' started by Reid Priedhorsky, Jul 12, 2005.

  1. Dear group,

    I'd have a class defined in one module, which descends from another class
    defined in a different module. I'd like the superclass to be able to
    access objects defined in the first module (given an instance of the first
    class) without importing it. Example of what I'm looking for:

    <<<file spam.py>>>

    class Spam(object):
    def fish(self):
    a = self.__module__.Ham()

    <<<file eggs.py>>>

    import spam

    class Eggs(spam.Spam):
    pass

    class Ham(object):
    pass

    The above doesn't work because __module__ is a string, not a module object:

    >>> import eggs
    >>> b = eggs.Eggs()
    >>> b.fish()

    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "spam.py", line 3, in foo
    a = self.__module__.Ham()
    AttributeError: 'str' object has no attribute 'Ham'

    (I suppose I could call __import__(self.__module__), but that seems kind
    of awkward.)

    Is this possible using Python 2.3? Any better ways to accomplish this?

    Thanks very much for any help,

    Reid
    Reid Priedhorsky, Jul 12, 2005
    #1
    1. Advertising

  2. "Reid Priedhorsky" <> wrote:

    > Dear group,
    >
    > I'd have a class defined in one module, which descends from another class
    > defined in a different module. I'd like the superclass to be able to
    > access objects defined in the first module (given an instance of the first
    > class) without importing it. Example of what I'm looking for:
    >
    > <<<file spam.py>>>
    >
    > class Spam(object):
    > def fish(self):
    > a = self.__module__.Ham()
    >
    > <<<file eggs.py>>>
    >
    > import spam
    >
    > class Eggs(spam.Spam):
    > pass
    >
    > class Ham(object):
    > pass
    >
    > The above doesn't work because __module__ is a string, not a module object:
    >
    > >>> import eggs
    > >>> b = eggs.Eggs()
    > >>> b.fish()

    > Traceback (most recent call last):
    > File "<stdin>", line 1, in ?
    > File "spam.py", line 3, in foo
    > a = self.__module__.Ham()
    > AttributeError: 'str' object has no attribute 'Ham'
    >
    > (I suppose I could call __import__(self.__module__), but that seems kind
    > of awkward.)
    >
    > Is this possible using Python 2.3? Any better ways to accomplish this?


    I don't know if it's "better", but since you know that self.__module__
    has already been imported, you can access it through the sys.modules
    dict:
    a = sys.modules[self.__module__].Ham()

    By the way, this seems like an error-prone hack. Are you sure you want
    to relate two independent classes just by the fact that they rely in
    the same file ? Remember, explicit is better than implicit.

    George
    George Sakkis, Jul 12, 2005
    #2
    1. Advertising

  3. On Mon, 11 Jul 2005 18:45:20 -0500, Reid Priedhorsky <> wrote:

    >Dear group,
    >
    >I'd have a class defined in one module, which descends from another class
    >defined in a different module. I'd like the superclass to be able to
    >access objects defined in the first module (given an instance of the first
    >class) without importing it. Example of what I'm looking for:
    >
    ><<<file spam.py>>>
    >
    > class Spam(object):
    > def fish(self):
    > a = self.__module__.Ham()
    >
    ><<<file eggs.py>>>
    >
    > import spam
    >
    > class Eggs(spam.Spam):
    > pass
    >
    > class Ham(object):
    > pass
    >
    >The above doesn't work because __module__ is a string, not a module object:
    >
    > >>> import eggs
    > >>> b = eggs.Eggs()
    > >>> b.fish()

    > Traceback (most recent call last):
    > File "<stdin>", line 1, in ?
    > File "spam.py", line 3, in foo
    > a = self.__module__.Ham()
    > AttributeError: 'str' object has no attribute 'Ham'
    >
    >(I suppose I could call __import__(self.__module__), but that seems kind
    >of awkward.)
    >
    >Is this possible using Python 2.3? Any better ways to accomplish this?
    >
    >Thanks very much for any help,
    >
    >Reid


    I think 2.3 will do this. But be careful not to tie your shoelaces together and trip --
    I haven't tested this beyond what you see. It was just an idea for the kind of access
    you seemed to want ;-)

    If each class and subclass whose global environment you want to reach through an instance
    provides a property that will return the class or subclass' global dict, then a base class
    method can access that via the instance to "fish" for a name in the appropriate "fishinghole"
    -- e.g.,

    ----< spam.py >-------------------------------
    """spam.py module doc string"""
    class Spam(object):
    def fish(self, whatfor):
    return self.fishinghole[whatfor]
    fishinghole = property(lambda self:globals()) # spam.py globals if this fishinghole used
    ----------------------------------------------

    ----< eggs.py >-------------------------------
    """eggs.py module doc string"""
    import spam

    class Eggs(spam.Spam):
    fishinghole = property(lambda self:globals()) # eggs.py globals if this fishinghole used

    class Ham(object):
    pass # won't find any fishing hole at all

    class Grits(spam.Spam):
    pass # no fishing hole, should find spam.py globals if looked for
    ----------------------------------------------

    >>> import eggs
    >>> dir(eggs)

    ['Eggs', 'Grits', 'Ham', '__builtins__', '__doc__', '__file__', '__name__', 'spam']
    >>> eggs.__doc__

    'eggs.py module doc string'
    >>>
    >>> e = eggs.Eggs()
    >>> e.fish('Ham')

    <class 'eggs.Ham'>
    >>> e.fish('__doc__')

    'eggs.py module doc string'
    >>> e.fishinghole.keys()

    ['Ham', 'spam', '__builtins__', '__file__', '__doc__', 'Grits', '__name__', 'Eggs']
    >>> g = eggs.Grits()
    >>> g.fish('Spam')

    <class 'spam.Spam'>
    >>> g.fish('__doc__')

    'spam.py module doc string'
    >>> g.fishinghole.keys()

    ['__builtins__', '__name__', '__file__', '__doc__', 'Spam']

    You could fish for a class that might be available in both modules by the same name,
    and get a different one depending on which instance' fish method or fishinghole you used.
    Here Spam is only available in spam.py, but if it were available in eggs.py then e.fish('Spam')
    would pick it up just like Ham.

    >>> spaminst = g.fish('Spam')()
    >>> spaminst.fish('__doc__')

    'spam.py module doc string'

    Note that the fishinghole property dynamically returns the module dict,
    which is mutable, so you can write a really tangled mess if you want to.
    This already seems dangerously close ;-)

    >>> e.fishinghole['x'] = 'x in eggs module globals'
    >>> e.fish('x')

    'x in eggs module globals'
    >>> eggs.x

    'x in eggs module globals'
    >>> g.fishinghole['x'] = 'x in spam module globals'
    >>> g.fish('x')

    'x in spam module globals'
    >>> eggs.spam.x

    'x in spam module globals'

    But we didn't directly import spam (eggs did, that's why eggs.spam was visible) ...
    >>> spam

    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    NameError: name 'spam' is not defined
    >>> import spam
    >>> spam.x

    'x in spam module globals'

    Regards,
    Bengt Richter
    Bengt Richter, Jul 12, 2005
    #3
    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. Evan Klitzke
    Replies:
    0
    Views:
    361
    Evan Klitzke
    Aug 2, 2007
  2. Ulrich Dorda
    Replies:
    4
    Views:
    439
  3. bart van deenen
    Replies:
    6
    Views:
    752
    bart van deenen
    Mar 3, 2009
  4. Chris Morris

    Execute code on descendant class init

    Chris Morris, Jan 3, 2004, in forum: Ruby
    Replies:
    6
    Views:
    109
    Chris Morris
    Jan 7, 2004
  5. Thomas
    Replies:
    4
    Views:
    166
    Thomas
    Jun 7, 2005
Loading...

Share This Page