metaclass and customization with parameters

zipher zondervanz at gmail.com
Sun Oct 3 17:32:16 EDT 2004


aleaxit at yahoo.com (Alex Martelli) wrote in message news:<1gl2s8a.1imgbyqcxntogN%aleaxit at 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



More information about the Python-list mailing list