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

metaclass and customization with parameters

P: n/a
After searching through comp.lang.python and the web regarding
metaclasses, I could not find an example for customing classes using
metaclass parameters.

I want to be able to create a class at runtime by calling some
function or 'meta-constructor' which returns a customized class and
sets a class attribute according a given parameter.

Ideally, I'd be able to do something like:
Bag = Metadict(filter=int) #Metadict returns a new class named 'Bag' issubclass(Bag, dict) # which is a type of dict True Bag.filter # with class attribute set accordingly <type 'int'> b = Bag({'pennies': 6.0, 'dimes': 3}) #create instances of this new class

(Aside: the issue of magically knowing the variable name (i.e. 'Bag')
in that first assignment statement and setting the class name
accordingly would be ideal, but I could live with passing the name as
a parameter to Metadict if necessary.)

There would also be a number of new and re-defined methods which would
be part of all classes constructed and returned by calls to Metadict.
For example, somewhere I need to re-define dict's __setitem__ method
to something like:
def __setitem__(self, key, value):

.... self[key] = self.filter(value) #coerce/validate values before
adding to dict

Ideally, all such methods would be in their own class definition since
they will be common to all classes created by Metadict (perhaps they
would need be defined within Metadict itself).
This seems like a simple thing to want, but unusally convoluted to
actually implement. I'm not even sure where to start.

Any pointers?

Thank you,

zipher
Jul 18 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
zipher <zo********@gmail.com> wrote:
After searching through comp.lang.python and the web regarding
metaclasses, I could not find an example for customing classes using
metaclass parameters.
When a class statement executes, Python determines the metaclass (e.g.
by finding a '__metaclass__' attribute in the class body) and then calls
it with three parameters -- never more, never fewer:

class name(bases):
__metaclass__ = metaboo
...rest of class body snipped...

is exactly equivalent to:

name = metaboo('name', bases, d)

where 'd' is the dict that remains after execution of the class body
(all barenames bound in the body -- be that by def, class, assignment,
import, whatever -- are left as entries in that 'd').
I want to be able to create a class at runtime by calling some
All classes are created at runtime, normally by executing (at runtime:
there is no other 'time'...;-) a 'class' statement.
function or 'meta-constructor' which returns a customized class and
sets a class attribute according a given parameter.

Ideally, I'd be able to do something like:
Bag = Metadict(filter=int) #Metadict returns a new class named 'Bag'
The normal Python syntax for that purpose might rather be:

class Bag:
__metaclass__ = Metadict
filter = int

and for that use, Medadict would be rather simple to write... but
your stated purpose (to this point) is even better accomplished by:

class Bag(dict):
filter = int
issubclass(Bag, dict) # which is a type of dict True Bag.filter # with class attribute set accordingly <type 'int'> b = Bag({'pennies': 6.0, 'dimes': 3}) #create instances of this new class

(Aside: the issue of magically knowing the variable name (i.e. 'Bag')
in that first assignment statement and setting the class name
accordingly would be ideal, but I could live with passing the name as
a parameter to Metadict if necessary.)


If you want to explicitly call Metadict as a factory, rather than use a
'class' statement, yep, there is then no way in which Metadict can know
what name its result will be bound to, so you'd have to pass it. But
why isn't a class statement even better?
There would also be a number of new and re-defined methods which would
be part of all classes constructed and returned by calls to Metadict.
For example, somewhere I need to re-define dict's __setitem__ method
to something like:
def __setitem__(self, key, value):
... self[key] = self.filter(value) #coerce/validate values before
adding to dict

Ideally, all such methods would be in their own class definition since
they will be common to all classes created by Metadict (perhaps they
would need be defined within Metadict itself).


No, this is best done by inheritance:

class Bag(filtered_dict):
filter = int

with, e.g:

class filtered_dict(dict):
def __setitem__(self, key, value):
dict.__setitem__(self, key, self.filter(value))
This seems like a simple thing to want, but unusally convoluted to
actually implement. I'm not even sure where to start.

Any pointers?


I would start with inheritance, because I don't see what value a custom
metaclass would add; indeed I see only downsides, such as needing to
pass the intended class name, if you want to use explicit-call syntax.

If it does turn out that subclasses of filtered_dict all DO need a
custom metaclass, for reasons connected to specs you haven't yet
mentioned, just add the metaclass (with a __metaclass__ in the body) to
filtered_dict, and every subclass thereof will inherit it. That's all
there is to it... class statement, and inheritance, appear to give you
all that you have required/explained so far, except the kind of syntax
you deem ideal (but is really second best, due to the need to pass a
class name...).
Alex
Jul 18 '05 #2

P: n/a
al*****@yahoo.com (Alex Martelli) wrote in message news:<1gl2s8a.1imgbyqcxntogN%al*****@yahoo.com>...
I want to be able to create a class at runtime by calling some


All classes are created at runtime, normally by executing (at runtime:
there is no other 'time'...;-) a 'class' statement.


Yes, I should have put that in quotes. What I meant to convey was
that I want to be able to create a class 'on the fly' without having
to define it first.
Ideally, I'd be able to do something like:
>> Bag = Metadict(filter=int) #Metadict returns a new class named

'Bag'


The normal Python syntax for that purpose might rather be:

class Bag:
__metaclass__ = Metadict
filter = int

and for that use, Medadict would be rather simple to write... but
your stated purpose (to this point) is even better accomplished by:

class Bag(dict):
filter = int


Yes, your suggestions were my second, and first implemenations
respectively. However, both require defining a class by the 'user',
so to speak, as opposed to letting the user simply call a 'function'
that returns the customized class with the filter class attribute
already set.

Another reason it would be helpful to be able to wrap this in an
expression like "Metadict(filter=int)" is because I can then use this
as a parameter passed to other parts of the application. (Although,
as you suggested, I'd have to pass the name as well.)

For example, in keeping with the aforementioned example, consider
creating a basic integer-weighted Graph class starting with the
following:

#A Graph is a dict whose values are Vertex.
#A Vertex is a dict whose values are int.
Graph = Metadict(name='Graph', filter=Metadict(name='Vertex', filter=int)) g = Graph() # create outgoing links on graph vertex 1 to 3,4,5: g[1] = {3: 1, 4: 2.0, 5: '3'} #this raw dict above will be converted to Vertex because
# of the Graph.filter function and assigned to g[1]
#Vertex.filter automatically coerced dict values to ints: g[1]

Vertex({3: 1, 4: 2, 5: 3})

But perhaps a simpler way to illustrate my intent is to just imagine a
series of dictionary classes which restrict all their values to a
certain type (through the filter function) before insertion into the
dictionary. Dictionaries of ints, lists, and strings along with
custom filters that, say, validate the values for correct spelling, or
whatever.

Now you ("I" ;^) don't want to require the user to create a new class
for every possible filtered dict variety. And, yes, you could avoid
this by just subclassing dict and passing the filter function to
__init__ and setting it as an instance attribute, but then you have an
extra attribute stored for every instance of your filtered dictionary
and the (albeit) small cost of assigning this attribute for every
instance created. (Consider again the Graph example, where there are
going to be many instances of the Vertex class within the Graph and
you don't want a unique filter function for each Vertex instance
within the Graph.)

This would seem like an ideal application for a metaclass (in the
abstract sense, not necessarily in the way Python implements the
concept): I want something that will create and return a specialized
class based on the parameters I pass to it.

Alex, thanks for your response.

zipher
Jul 18 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.