Metaklasse funktioniert nicht!

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Deever
User
Beiträge: 15
Registriert: Samstag 30. Juli 2005, 12:46

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
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

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__
TUFKAB – the user formerly known as blackbird
Antworten