Dynamic class construction?
David C. Ullrich
ullrich at math.okstate.edu
Sun Jan 30 14:20:46 EST 2000
Nic Williams wrote:
> 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.
Of course they need to have different names, I was wondering if
there would be an internal problem with identical __name__'s. I
gather not, thanks.
(Here for example I'll have
G1 = NewGroup(something)
G2 = NewGroup(somethingelse)
and then G1.__name__ and G2.__name__ would both be
"new".)
>
> 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:
I don't know that I want to - I was wondering if I needed to.
Couldn't hurt.
>
> 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.
Yup, thanks.
<sigh>
I tried simply setting the value of __name__ to what
I wanted, and I got an error about read-only attributes.
At least I _thought_ I'd tried that - works fine today.
It may be time-of-day-dependent.
</sigh>
I take it that simply putting a "pass" in the inner
class definition and then setting attributes _is_ the
"right" thing? It wasn't the first thing I thought of,
but it was the first thing that worked.
Thanks,
DU
More information about the Python-list
mailing list