Dynamic class construction?

Nic Williams nic at csee.uq.edu.au
Sat Jan 29 21:24:03 EST 2000


In article <389309F7.4A35371F at math.okstate.edu>,
  "David C. Ullrich" <ullrich at math.okstate.edu> wrote:

Just for reference, this is Part i.

>     Say I want to make a function that returns a new _class_.
> I can do this:
>
> def NewClass(whatever):
>     class new(baseClass):
>         pass
>     new.SomeAttribute = whatever.whatever
>     return new
>
> and it seems to do the job. Is there another way to
> do this that seems much better for some reason?

and the next question is part ii.
I'll answer part ii first (helps explain part i soln)

>     I guess a related question would be whether
> having distinct classes with the same __name__
> is going to be trouble - does __name__ get used
> in significant ways internally or is it just there
> for the programmer's convenience?

A class's name when the class is first defined is used in two ways:
i) internal information (so you can ask a class object who it is)
ii) binding information within the namespace

A good way to demonstrate this is with the following example:
>>> class FirstName:
...     pass
...
>>> FirstName
<class __main__.FirstName at e6fe0>
>>> FirstName.__name__ = 'SecondName'
>>> FirstName
<class __main__.SecondName at e6fe0>
>>> SecondName
Traceback (innermost last):
  File "<stdin>", line 1, in ?
NameError: SecondName

Note here that when we change the class's internal name, it now thinks
that it's name is SecondName, but the namespace's binding still calls it
FirstName.

See py doc: http://www.python.org/doc/current/ref/execframes.html

So you can multiple classes who think internally they are the same name,
but they must be named differently if they lie in the same namespace.

Ok, back to part i.

With your example above and below we see that the binding name within
the global namespace is determined by the attribute G. Note that there
is also no class called 'new' anywhere at the end of the method (it was
declared within the local namespace which disappeared at the end of the
method).

So we have an object whose internal name is 'new' but its binding is
'G'. If you want to change the class's internal name to that of its
external binding, use something like:


def newClass(name, ops, superclass):
	class NewClass(superclass):
		pass
	for op in ops.keys():
		setattr(NewClass, op, ops[op])
	NewClass.__name__ = name
	return NewClass

def anOp(self):
	return 'This is an instance of the class %s' % \
		self.__class__.__name__

someOps={'__str__':anOp}
G=newClass('G', someOps, Group) # Group defined elsewhere
print G
<class __main__.G at f92a8>

BINGO. It's name binding and internal naming now match.

Hope that answered the question.

Nic


>     (In case someone feels the answer might depend
> on the context: it's mathematical structures. For
> example baseClass might be Group; a subclass
> of Group "is" a group, and an instance of the
> subclass "is" an element of the group. So I might
> want to create a group using
>
> def NewGroup(groupOp):
>     class new(Group):
>         pass
>     new.__mul__ = groupOp
>     return new
>
> so then
>
> G = NewGroup(SomeGroupOp)
> g1 = G(someparams)
>
> makes g1 an element of the group G.)
>
>


Sent via Deja.com http://www.deja.com/
Before you buy.



More information about the Python-list mailing list