Seite 1 von 1

Metaklasse funktioniert nicht!

Verfasst: Dienstag 10. Januar 2006, 23:39
von Deever
Hey Amigos, wie geht's?

Code: Alles auswählen

class Meta(type):
	def __new__(cls,name,bases,d):
		print 'Meta.__new__ called!'
		return super(Meta,cls).__new__(name,bases,d)
	def __init__(self,name, bases, d):
		print 'Meta.__init__ called!'
		super(Meta,self).__init__(name,bases,d)
	def __call__(self,*args):
		print 'Meta.__call__ called!'
		return super(Meta,self).__call__(*args)

class Foo:
	__metaclass__=Meta
liefert nur

Code: Alles auswählen

Meta.__new__ called!

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in -toplevel-
    class Foo:
  File "<pyshell#0>", line 4, in __new__
    return super(Meta,cls).__new__(name,bases,d)
TypeError: Error when calling the metaclass bases
    type.__new__(X): X is not a type object (str)
Wie ließe sich das Problem beheben? Ich habe auch schon eine Reihe weiterere Metaklassen probiert, aber bisher war noch keine einzige in der Lage, funktionstüchtige Klassenobjekte zu erstellen.

Gruß,
/dev

Verfasst: Mittwoch 11. Januar 2006, 04:53
von mitsuhiko
Das kann nicht funktionieren. 1.) klassen mit metaklassen müssen object sein. 2.) hast du das system der Metaklasse nicht verstanden, da wird nix weitergeleitet.
Vielleicht hiflt dir das:

Code: Alles auswählen

class Meta(type):

    def __new__(cls, name, bases, d):
        print 'Meta.__new__'
        result = type.__new__(cls, name, bases, d)
        def __init(self):
            print 'Meta.__init__'
        def __call(self):
            print 'Meta.__call__'
        setattr(result, '__init__', __init)
        setattr(result, '__call__', __call)
        return result


class BetterMeta(type):

    def __new__(cls, name, bases, d):
        print 'BetterMeta.__new__'
        result = type.__new__(cls, name, bases, d)
        def __init(self, *args, **kwargs):
            print 'BetterMeta.__init__'
            if '__init__' in d:
                d['__init__'](self, *args, **kwargs)
        def __call(self, *args, **kwargs):
            print 'BetterMeta.__call__'
            if '__call__' in d:
                d['__call__'](self, *args, **kwargs)
        setattr(result, '__init__', __init)
        setattr(result, '__call__', __call)
        return result


class Foo(object):
    __metaclass__ = Meta


class BetterFoo(object):
    __metaclass__ = BetterMeta
    def __call__(self):
        print 'BetterFoo.__call__'

if __name__ == '__main__':
    print '> erstelle foo'
    f = Foo()
    print '> rufe foo auf'
    f()
    print '> erstelle betterfoo'
    f2 = BetterFoo()
    print '> rufe betterfoo auf'
    f2()
Ausgabe:

Code: Alles auswählen

blackbird@volverine:~/Developement/area51$ python metacls.py
Meta.__new__
BetterMeta.__new__
> erstelle foo
Meta.__init__
> rufe foo auf
Meta.__call__
> erstelle betterfoo
BetterMeta.__init__
> rufe betterfoo auf
BetterMeta.__call__
BetterFoo.__call__