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

Making classes from Metaclasses globally available

P: n/a
Hello,

I'm using MetaClasses to create classes.

How do I make these new classes "globally" available?

I probably just have to assign them to something magic, but I can't seem to
figure out which one.

if I do:

MetaClass('Klass', (), {})

The resulting class needs to be assigned to something:

myclass = MetaClass('Klass', (), {})

The problem is that I'm looping and don't know in advance how many classes
there will be.

So right now I have something like:

msclasses[clsname] = MapServerMetaClass(str(clsname), (),
{'schema':list,'__init__':MapServerClassInit})

inside a loop.

Problem is I really don't want to have the classes stuck inside that dict.
I want them "globally" available as if I had simply made a "class"
declaration at the top of the file.

Any ideas or suggestions?

Thanks,
J.F.
Jul 18 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
Jean-François Doyon wrote:
I'm using MetaClasses to create classes.

How do I make these new classes "globally" available?


As far as I can see, your problem has nothing to do with metaclasses.
globals()["foo"] = 1
foo

1

Substitute 1 in the above with your new class, and there you are. Note,
however, that dynamically inserting variables is not the best programming
practice. When you don't know the variable name in advance, what would be
the benefit of being able to access the object via its identifier?

Peter

Jul 18 '05 #2

P: n/a
Jean-François Doyon wrote:
Hello,

I'm using MetaClasses to create classes.

How do I make these new classes "globally" available?

I probably just have to assign them to something magic, but I can't seem
to figure out which one.

if I do:

MetaClass('Klass', (), {})

The resulting class needs to be assigned to something:

myclass = MetaClass('Klass', (), {})


Just do

class Klass(object):
__metaclass__ = MetaClass

Cheers

Stephan
Jul 18 '05 #3

P: n/a
Peter Otten <__*******@web.de> writes:
Note, however, that dynamically inserting variables is not the best
programming practice. When you don't know the variable name in
advance, what would be the benefit of being able to access the
object via its identifier?


When _who_ doesn't know the variable name in advance of _what_ ?

dir() [ <stuff> ] from foo import *
dir(foo) [ <stuff>, 'hello'] hello() 'Hello, World!'

Here we dynamically inserted variables not known beforehand to the
user, even if they were known beforehand to the module writer.

Not convinced?

OK ...
from treebuilder import build_structure_from_xml_tree
dir() [ <stuff> ] build_structure_from_xml_tree('fubar.xml')
dir() [ <stuff>, 'root' ] dir(root)

['branch1', 'branch2']
Here we dynamically inserted variables not known beforehand to the
author of the module, which may or may not have been known to the
user. If the user were the author of fubar.xml then, presumably he
would know the variable names; if he were not, then he may well not
know them beforehand. Either way he is likely to want to access them by
name.

.... still not convinced ?

I have a program which parses C++ header files and creates Python
proxies for the stuff found therein, allowing you to interact with
objects in C++ libraries. You load something we call a dictionary
(which describes the library) and the program uses that information to
create, dynamically, Python objects with the same names and structures
as the C++ classes in the library.

The author of the program certainly does not know the names of the
objects the program is going to create in the future. The client may
know them (he might be wanting to rewrite some C++ code in Python), or
not (he might be wanting to use Python's introspection capabilities to
poke around the C++ library).
Jul 18 '05 #4

P: n/a
Jacek Generowicz wrote:
Peter Otten <__*******@web.de> writes:
Note, however, that dynamically inserting variables is not the best
programming practice. When you don't know the variable name in
advance, what would be the benefit of being able to access the
object via its identifier?
When _who_ doesn't know the variable name in advance of _what_ ?


I may be fighting with the english language here - and lose...
dir() [ <stuff> ] from foo import *
dir(foo) [ <stuff>, 'hello'] hello() 'Hello, World!'

Here we dynamically inserted variables not known beforehand to the
user, even if they were known beforehand to the module writer.


I've taken to avoid the * import, but at least I would hope that you
- had a quick look at the foo documentation before you chose to import it
- follow the convention of placing import statements at the beginning of the
module, and therefore can write your own help() function with some
confidence that it will not be inadvertently replaced by foo.help
Not convinced?
You guessed it.
OK ...
from treebuilder import build_structure_from_xml_tree
dir() [ <stuff> ] build_structure_from_xml_tree('fubar.xml')
dir() [ <stuff>, 'root' ] dir(root)
['branch1', 'branch2']
Here we dynamically inserted variables not known beforehand to the
author of the module, which may or may not have been known to the
user. If the user were the author of fubar.xml then, presumably he
would know the variable names; if he were not, then he may well not
know them beforehand. Either way he is likely to want to access them by
name.


OK. Now show me the demo again with an XML document along the lines of

<dir><file/><file/></dir>

In principle I have no problem with the dynamically chosen attribute names -
just hope my example would *not* result in the creation of fileN attributes
- but why can't your function_with_a_long_name() just return the root
*object* and let the user decide about the appropriate name - or at least
take a namespace as its second argument?
... still not convinced ?
This is even worse.
I have a program which parses C++ header files and creates Python
proxies for the stuff found therein, allowing you to interact with
objects in C++ libraries. You load something we call a dictionary
(which describes the library) and the program uses that information to
create, dynamically, Python objects with the same names and structures
as the C++ classes in the library.

The author of the program certainly does not know the names of the
objects the program is going to create in the future. The client may
know them (he might be wanting to rewrite some C++ code in Python), or
not (he might be wanting to use Python's introspection capabilities to
poke around the C++ library).


As far as I can judge from the description, this is perfectly OK with me.
The recommendation to avoid dynamic manipulations of the global namespace
was not meant as a rule carved in stone, but rather a means to write
cleaner code and avoid errors that may be hard to reproduce.

Peter

PS: I'm glad I didn't also warn the OP against using metaclasses with as
little information as his code snippets and lack of knowledge of the
globals() function. I admit I was tempted...

Jul 18 '05 #5

P: n/a
Peter Otten <__*******@web.de> writes:
Jacek Generowicz wrote:
Peter Otten <__*******@web.de> writes:
Note, however, that dynamically inserting variables is not the best
programming practice. When you don't know the variable name in
advance, what would be the benefit of being able to access the
object via its identifier?
When _who_ doesn't know the variable name in advance of _what_ ?


I may be fighting with the english language here - and lose...


Don't think so; I was merely trying to point out that "you" can have
different meanings in this context (program author, program client),
and that the same is true of "in advance" (before the program is
written, before the program is run).
I've taken to avoid the * import,
Yes, I advise my Python students not to do it ... however a there are
some standard modules which are designed to be imported like this.
- but why can't your function_with_a_long_name() just return the root
*object* and let the user decide about the appropriate name
This only works if your objects share a single common root.

To be honest, that is exactly what my functions of this type do
(though in one case I would like to try having a third namespace
similar to globals and builtins where to shove all this stuff
.... unfortunately I haven't found a satisfactory way of creating one
yet.)

Still, what you are doing is programatically adding attributes to some
namespace ... and maybe the user should have the option of dumping
those attributes in the global namespace, just like he does with
"import".
The recommendation to avoid dynamic manipulations of the global namespace
was not meant as a rule carved in stone, but rather a means to write
cleaner code and avoid errors that may be hard to reproduce.


You asked

When you don't know the variable name in advance, what would be the
benefit of being able to access the object via its identifier?

I merely took your question literally (even though it was probably
rhetorical) and offered examples of such use cases (probably
rhetorically :-).

In summary, the answer is:

Just because the author of the code does not know the the name at
the time he writes the code, does not mean that the code's client
cannot know the name before he runs the code.
Jul 18 '05 #6

P: n/a
Jacek Generowicz wrote:
Peter Otten <__*******@web.de> writes:
Jacek Generowicz wrote:
> Peter Otten <__*******@web.de> writes:
>
>> Note, however, that dynamically inserting variables is not the best
>> programming practice. When you don't know the variable name in
>> advance, what would be the benefit of being able to access the
>> object via its identifier?
>
> When _who_ doesn't know the variable name in advance of _what_ ?
I may be fighting with the english language here - and lose...


Don't think so; I was merely trying to point out that "you" can have
different meanings in this context (program author, program client),
and that the same is true of "in advance" (before the program is
written, before the program is run).


OK, I missed that point the first time.
- but why can't your function_with_a_long_name() just return the root
*object* and let the user decide about the appropriate name


This only works if your objects share a single common root.


For everything else, there are tuples or the Bunch class.
Still, what you are doing is programatically adding attributes to some
namespace ... and maybe the user should have the option of dumping
Stop, no further from here...
those attributes in the global namespace, just like he does with
"import".
Too late :-)
The recommendation to avoid dynamic manipulations of the global namespace
was not meant as a rule carved in stone, but rather a means to write
cleaner code and avoid errors that may be hard to reproduce.


You asked

When you don't know the variable name in advance, what would be the
benefit of being able to access the object via its identifier?

I merely took your question literally (even though it was probably
rhetorical) and offered examples of such use cases (probably
rhetorically :-).


You also slightly broadened the context. I may have been too sure about how
the OP would answer it, but the above question may as well serve as the
criterion whether to stick with the original dictionary or use a class
(including modules created on the fly, I tried that just now and it seems
to work). I'm still convinced that the generation code, the generated code,
and the client code should each have its own namespace.
In summary, the answer is:

Just because the author of the code does not know the the name at
the time he writes the code, does not mean that the code's client
cannot know the name before he runs the code.


D'accord. Again, a class offers benefits over a module here, as you can
lazily create the objects, when the client accesses them. E. g.:

class Lift(list):
_globals = {}
def __getattr__(self, name):
exec """
def lift(self):
for item in self:
yield item.%s
""" % name in Lift._globals
lift = Lift._globals["lift"]
setattr(Lift, name, property(lift))
return lift(self)

if __name__ == "__main__":
class Person:
def __init__(self, name):
self.name = name
people = Lift(map(Person, "Peter Paul Mary".split()))
print list(people.name)

Across all Lift instances, __getattr__() will only be called once for every
name.
Or maybe I just prefer AttributeError over NameError...

Peter

Jul 18 '05 #7

P: n/a
On Wed, 16 Jun 2004 00:28:46 -0400, "Jean-François Doyon"
<jf*****@methane.ca> wrote:
Hello,

I'm using MetaClasses to create classes.
Why use metaclasses? The metaclass wizards seem to be telling us that
these are special tools for Python developers, not intended for
"mortal users".
How do I make these new classes "globally" available?
Can't you just generate your classes with an ordinary function, and
assign them to whatever global name you want?

def factory(var1,func1):
class C:
const1 = 123
def commonfunc(self):
print "Hello from commonfunc"
setattr(C, 'var1', var1)
setattr(C, func1.__name__, func1)
return C

Then whenever you need a new class, just call the factory with
whatever variable data and functions you want to add to each class.

C1 = factory(var1,func1) # A unique class
c1 = C1() # An instance of that class

-- Dave

************************************************** *********** *
* David MacQuigg, PhD * email: dmq at gain.com * *
* IC Design Engineer * phone: USA 520-721-4583 * * *
* Analog Design Methodologies * * *
* * 9320 East Mikelyn Lane * * *
* VRS Consulting, P.C. * Tucson, Arizona 85710 *
************************************************** *********** *

I probably just have to assign them to something magic, but I can't seem to
figure out which one.

if I do:

MetaClass('Klass', (), {})

The resulting class needs to be assigned to something:

myclass = MetaClass('Klass', (), {})

The problem is that I'm looping and don't know in advance how many classes
there will be.

So right now I have something like:

msclasses[clsname] = MapServerMetaClass(str(clsname), (),
{'schema':list,'__init__':MapServerClassInit})

inside a loop.

Problem is I really don't want to have the classes stuck inside that dict.
I want them "globally" available as if I had simply made a "class"
declaration at the top of the file.

Any ideas or suggestions?

Thanks,
J.F.


Jul 18 '05 #8

P: n/a
In article <Y%*********************@news20.bellglobal.com>,
Jean-François Doyon <jf*****@methane.ca> wrote:

I'm using MetaClasses to create classes.


Why? I'm serious; until we understand what you're trying to accomplish,
we can't tell you the best way to accomplish your task.
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

"Typing is cheap. Thinking is expensive." --Roy Smith, c.l.py
Jul 18 '05 #9

P: n/a
Why?

Well, basically I'm looking at writing an IDE of sorts. It should allow the
viewing editing of text files.

Catch is, said text files are structured much like XML, but they're NOT XML.

I want the application to be extensible, and not be stuck to a particular
version/schema of this file.

So the idea is, create one or more "schemas" to describe what I'm going to
be looking for and then parsing.

Because the format of said text file is structured in a very XML-like way, I
thought it'd make sense to simply
dynamically create a tree of objects, which are instances of relevant
classes. But because of my statement above
I don't know in advance what classes there might be and so on.

So I figured I'd use something like MetaClasses to do it. I've got the
basic schema parsing and class creation
in place already, the problem is that I want to keep the class creation and
the parsing fairly seperate.

I'm thinking the parsing functionality will be extra polated from the schema
also, but be part of the classes (The
file structure is consistent enough to allow this I think ...).

Anyways, it's not all entirely clear in my mind yet ... But that's the basic
idea.

But I just want classes created from the schema to be available globally so
that when the classes need to interact with each
other (More precisely, one instance needs to instanciate another class and
make it an attribute of self) I don't need to pass
a list of classes or soemthing similar around everywhere.

Did that make any sense ? :)

Admitedly, I've kind of thought up a way to do it with a unique class ...
But I don't like that design as much ... The model
I describe above fits really well with the application in question. I've
even seen something similar done in PHP with a
web interface, though it was much more restricted in it's flexibility and
capability to adapt to any kind of schema.

Metaclasses seem to open the door to greater flexibility by not having to
know ANYTHING in advance.

If you're familiar with the generateDS script, I've got something like that
in mind, but not for XML.

If anyone has a better idea on how to go about this, or knows of
tools/examples that implement this kind of scenario,
I'd love to hear about it!

Thanks,
J.F.
"Jean-François Doyon" <jf*****@methane.ca> wrote in message
news:Y%*********************@news20.bellglobal.com ...
Hello,

I'm using MetaClasses to create classes.

How do I make these new classes "globally" available?

I probably just have to assign them to something magic, but I can't seem to figure out which one.

if I do:

MetaClass('Klass', (), {})

The resulting class needs to be assigned to something:

myclass = MetaClass('Klass', (), {})

The problem is that I'm looping and don't know in advance how many classes there will be.

So right now I have something like:

msclasses[clsname] = MapServerMetaClass(str(clsname), (),
{'schema':list,'__init__':MapServerClassInit})

inside a loop.

Problem is I really don't want to have the classes stuck inside that dict.
I want them "globally" available as if I had simply made a "class"
declaration at the top of the file.

Any ideas or suggestions?

Thanks,
J.F.

Jul 18 '05 #10

P: n/a
Jacek Generowicz <ja**************@cern.ch> wrote in message news:<ty*************@pcepsft001.cern.ch>...
(though in one case I would like to try having a third namespace
similar to globals and builtins where to shove all this stuff
... unfortunately I haven't found a satisfactory way of creating one
yet.)


I do not understand what the problem is ... you can just create a
class (or instance) called namespace, put it in __builtin__ and call
all the names in this custom namespace as namespace.myname.
Maybe you do not like to tweak with __builtin__ (which I can understand);
another option is to use a dynamically created module to fake a namespace:

import sys
from types import ModuleType

sys.modules["namespace"] = ModuleType("namespace",
"""This is a dynamically generated module used to
fake a namespace.""")

#populate it with setattr, getattr
I am sure you thought to this solution too, so what is unsatisfactory about it?
Just to know,
Michele Simionato
Jul 18 '05 #11

P: n/a
Peter Otten <__*******@web.de> writes:
I'm still convinced that the generation code, the generated code,
and the client code should each have its own namespace.


I agree with you in principle ... it's just these pesky users who
sometimes insist on having it all in the global one :-)
Jul 18 '05 #12

P: n/a
mi***************@poste.it (Michele Simionato) writes:
I do not understand what the problem is ... you can just create a
class (or instance) called namespace, put it in __builtin__ and call
all the names in this custom namespace as namespace.myname. Maybe you do not like to tweak with __builtin__ (which I can understand);
another option is to use a dynamically created module to fake a namespace: I am sure you thought to this solution too, so what is
unsatisfactory about it? Just to know,


Having to specify the namespace explicitly. I want this namespace to
be looked in _automatically_ just like the global and __builtin__
namespaces are, yet I want it to be separate from global and
__builtin__ to provide a way out when names clash.
Jul 18 '05 #13

P: n/a
"Jean-François Doyon" <jf*****@methane.ca> wrote in message news:<5d*********************@news20.bellglobal.co m>...
Why?

Well, basically I'm looking at writing an IDE of sorts. It should allow the
viewing editing of text files.

Catch is, said text files are structured much like XML, but they're NOT XML.

I want the application to be extensible, and not be stuck to a particular
version/schema of this file.

So the idea is, create one or more "schemas" to describe what I'm going to
be looking for and then parsing.

Because the format of said text file is structured in a very XML-like way, I
thought it'd make sense to simply
dynamically create a tree of objects, which are instances of relevant
classes. But because of my statement above
I don't know in advance what classes there might be and so on.

So I figured I'd use something like MetaClasses to do it. I've got the
basic schema parsing and class creation
in place already, the problem is that I want to keep the class creation and
the parsing fairly seperate.

I'm thinking the parsing functionality will be extra polated from the schema
also, but be part of the classes (The
file structure is consistent enough to allow this I think ...).

Anyways, it's not all entirely clear in my mind yet ... But that's the basic
idea.

But I just want classes created from the schema to be available globally so
that when the classes need to interact with each
other (More precisely, one instance needs to instanciate another class and
make it an attribute of self) I don't need to pass
a list of classes or soemthing similar around everywhere.

Did that make any sense ? :)

Admitedly, I've kind of thought up a way to do it with a unique class ...
But I don't like that design as much ... The model
I describe above fits really well with the application in question. I've
even seen something similar done in PHP with a
web interface, though it was much more restricted in it's flexibility and
capability to adapt to any kind of schema.

Metaclasses seem to open the door to greater flexibility by not having to
know ANYTHING in advance.

If you're familiar with the generateDS script, I've got something like that
in mind, but not for XML.

If anyone has a better idea on how to go about this, or knows of
tools/examples that implement this kind of scenario,
I'd love to hear about it!

Thanks,
J.F.


Do you know about David Mertz's article on XML and declarative mini-languages?
It appeared some time ago on IBMdeveloperWorks. In the scenario you are
showing to us metaclasses could be indeed a sensible solution, but not
necessarely the best one.
Michele Simionato
Jul 18 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.