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