Play with classes

Jacek Generowicz jacek.generowicz at cern.ch
Fri Feb 27 04:04:31 EST 2004


Zunbeltz Izaola <zunbeltz at wm.lc.ehu.es.XXX> writes:

> Jacek Generowicz <jacek.generowicz at cern.ch> writes:
> 
> Thank for the help.

I hope that it is what you were asking for.

Of course, my posting such a solution should in no way be interpreted
as a suggestion that it is appropriate to your _real_ problem. You may
well want a completely different approach, but I can't tell without
knowing more about your application.

> > __metaclass__ = type
> 
> I am not an expert and i don't understand very well things like 
> __metaclass__, but it not redundat this line? From the Language Reference
> 
> """
> __metaclass__
>     This variable can be any callable accepting arguments for name, bases,
>  and dict. Upon class creation, the callable is used instead of the 
> built-in type(). New in version 2.2. 
> """
> 
> so I think __metaclass__ = type is the same as not defining __metaclass__

It is indeed tempting to conclude that from what you have quoted.

One of the beauties of Python is its highly interactive nature, and
the ease with which you can try things out. Your hypothesis that
"__metaclass__ = type is the same as not defining __metaclass__" can
be refuted by the Python interpreter itself within about 10 seconds of
work. Take the code I sent, remove the binding of __metaclass__ and
run the code. You will find that Python replies:

  TypeError: a new-style class can't have only classic bases

As written in my example, ("class ModeA: pass" etc.) all the classes
are classic, because they do not inherit from object.

>>> class classic: pass
... 
>>> class newstyle(object): pass
... 
>>> type(classic)
<type 'class'>
>>> type(newstyle)
<type 'type'>

I want them to be new-style classes, because I am going to create new
classes which inherit from them, using type. This means of creating
classes creates new-style classes, and new style classes, as the error
message above suggests, "can't have only classic bases".

So, I could either make ModeA & co inherit from object, or I could
make all classes new-style ones by default, by binding __metaclass__
to type.

Alternatively, I could not use type to create the UserClasses, but
types.ClassType (types is a module). Alternatively I could use use
type(ModeA) which would pick the appropriate metaclass for creation of
your UserClasses depending on the situation.

> """
> __metaclass__
>     This variable can be any callable accepting arguments for name, bases,
>  and dict. Upon class creation, the callable is used instead of the 
> built-in type(). New in version 2.2. 
> """

Hmm. Is that a documentation bug? I suspect that it should read "
... instead of types.ClassType"


[ So, here's a classic class version of the original:

class ModeA: pass
class ModeB: pass
class TypeA: pass
class TypeB: pass
class TypeC: pass
class SubtypeA: pass
class SubtypeB: pass

collect_bases = [(Mode, Type, Subtype)
                 for Mode in [ModeA, ModeB]
                 for Type in [TypeA, TypeB, TypeC]
                 for Subtype in [SubtypeA, SubtypeB]]

count = 0
for bases in collect_bases:
    name = "UserClass%d" % count
    globals()[name] = type(ModeA)(name, bases, {})
    # or you could "import types" and do the following
    # globals()[name] = types.ClassType(name, bases, {})
    count += 1

]



More information about the Python-list mailing list