Access descendant class's module namespace from superclass

R

Reid Priedhorsky

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:
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
 
G

George Sakkis

Reid Priedhorsky said:
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:

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
 
B

Bengt Richter

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:

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')
>>> 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')
>>> 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.
'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) ... Traceback (most recent call last):
'x in spam module globals'

Regards,
Bengt Richter
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top