By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,089 Members | 2,226 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,089 IT Pros & Developers. It's quick & easy.

Access descendant class's module namespace from superclass

P: n/a
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
Jul 21 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
"Reid Priedhorsky" <re**@reidster.net> 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

Jul 21 '05 #2

P: n/a
On Mon, 11 Jul 2005 18:45:20 -0500, Reid Priedhorsky <re**@reidster.net> 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
Jul 21 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.