Referencing module.instance
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Fri Dec 2 20:24:26 EST 2011
On Fri, 02 Dec 2011 09:49:25 -0800, Gnarlodious wrote:
> What I am doing is importing modules that have an identical instance
> name. So I say:
>
> import Grid
>
> Grid has its instance:
>
> Grid.Grid()
>
> and this is the same for all modules of my webapp. allowedPages is a
> list of modules to import, so they are quoted strings:
>
> for page in self.allowedPages:
> setattr(self, page, __import__(page))
So if allowedPages looks like this: ['Grid', 'Spam', 'Ham', 'Cheese'] you
expect your instance to look like this:
self.Grid # has the value Grid.Grid
self.Spam # has the value Spam.Grid etc.
self.Ham
self.Cheese
Correct?
I'm not sure I like that design, it feels wrong, but perhaps I don't
understand the reason for it. Moving along...
> The problem is that the attribute name needs to reference the Grid.Grid
> instance and not the Grid module. How would I do this? I can do it
> literally:
> setattr(self, 'Grid', Grid.Grid)
>
> however doing it as a reference eludes me.
__import__(page) returns a module, so just grab that attribute from the
module.
for page in self.allowedPages:
setattr(self, page, __import__(page).Grid)
But note that this is an binding operation, like an assignment. If you
rebind module.Grid, your instance self will not see the change:
Spam.Grid = 42 # some value
instance.read_pages() # whatever you call the method
assert instance.Spam == 42
Spam.Grid = 23 # rebind the original
assert instance.Spam == 23 # THIS WILL FAIL!!!
If you need these attributes to be aliases to the module attribute,
rather than independent bindings, you need to use computed properties
rather than plain attributes. I leave that as an exercise, mainly because
I suspect it will be very difficult.
Wait... no, I think it's easy! (Famous last words...) Try this untested
code:
class MyClass(object):
allowedPages = ('Grid', 'Spam', 'Ham', 'Cheese')
def __init__(self):
self.modules = {}
for name in allowedPages:
self.modules[name] = __import__(name)
def __getattribute__(self, name):
if name in self.allowedPages:
return self.modules[name].Grid
return super(MyClass, self).__getattribute__(name)
--
Steven
More information about the Python-list
mailing list