Metaclasses broke in 2.2?

Drew Csillag drew_csillag at geocities.com
Tue Aug 14 12:32:07 EDT 2001


On Tue, Aug 14, 2001 at 11:42:15AM -0400, Guido van Rossum wrote:
> [Drew Csillag]
> > > > I don't know if this was intended, but it appears that the metaclass
> > > > instantiation doesn't work with Python 2.2a1.  Are the old metaclass
> > > > things no longer supported in 2.2 or is it just temporarily broken?
> 
> [Guido]
> > > Can you be more specific?  What old metaclass are you referring to?
> > > It's probably broken because I changed the Don Beaudry hook invocation
> > > to favor the new metaclass mechanism that is central to the new types
> > > in 2.2.
> 
> [Drew]
> > Take any of the code in Demo/metaclasses in 2.2a1.  You get tracebacks
> > of the variety:
> > 
> > Traceback (most recent call last):
> >   File "Eiffel.py", line 113, in ?
> >     _test()
> >   File "Eiffel.py", line 101, in _test
> >     class C(Eiffel):
> > TypeError: cannot create 'instance' instances
> > drew:~/build/Python-2.2a1/Demo/metaclasses>../../python Enum.py 
> > Traceback (most recent call last):
> >   File "Enum.py", line 169, in ?
> >     _test()
> >   File "Enum.py", line 128, in _test
> >     class Color(Enum):
> > TypeError: cannot create 'instance' instances
> > drew:~/build/Python-2.2a1/Demo/metaclasses>
> > 
> > I guess the real question is: "how does one go about writing metaclasses
> > in Python code in 2.2?"
> 
> I see.  You will be able to subclass from 'type' (or types.TypeType if
> you prefer :-).  Right now this doesn't work right (neiter in 2.2a1
> nor in CVS) so I can't post a working demo :-(
> 
> But here's something that you *should* be able to write:
> 
> class mytype(type):
>     def __new__(*args):
>         print "mytype.__new__" + str(args)
>         return type.__new__(*args)
> 
> class C:
>     __metaclass__ = mytype
> 
> print C.__class__		# <type 'mytype'>
> a = C()
> print a.__class__		# <type 'C'>

Another question is: will you be able to inherit from C and get the same
behavior as the current situation where ideally this would work:

class meta:
    def __init__(self, klass, bases, dict):
        pass

class foo:
    __metaclass__ = meta
print 'foo is', foo  # foo *is* an meta instance

class bar(foo): pass # dies here
print 'bar is', bar  # would be lovely if bar was an instance of meta

Similar to the old (pre 2.2) way which would look like this:


class meta:
    def __init__(self, klass, bases, dict):
        pass

m = meta(1,3,3)

class foo(m): pass
print 'foo is', foo
# prints -> foo is <__main__.meta instance at 80da338>

class bar(foo): pass
print 'bar is', bar
# prints -> bar is <__main__.meta instance at 80da358>


Yes, you can inherit from type but it doesn't really produce the desired
behavior:


class meta: #can inherit from type or set __metaclass__, output is the same
    __metaclass__ = type
    def __init__(self, klass, bases, dict):
        pass

class foo(meta): pass
print 'foo is', foo
#prints -> foo is <type 'foo'>

class bar(foo): pass 
print 'bar is', bar
#prints -> bar is <type 'bar'>


In this case, foo and bar are type objects, not instances of meta,
which is what I'm looking to do.  Is this part of what you were saying
about it not working yet, or has my head exploded without my knowledge
and I'm overlooking the obvious?

I guess what I'm really trying to say is that for a library I
currently have using 2.1, currently the user can be totally ignorant
of the fact that they are not defining regular classes, but
metaclasses, and ideally, I'd like to keep it that way.

Drew

-- 
print(lambda(m,d,y):['Sun','Mon','Tues','Wed','Thurs','Fri','Satur'][(
lambda(m,d,y):(23*m/9+d+4+y/4-y/100+y/400)%7)(m<3and(m,d+y,y-1)or(m,
d+(y-2),y))])(map(int,raw_input('mm/dd/yyyy>').split('/')))+'day'




More information about the Python-list mailing list