import string

class Luokkatyyppi:
        def __init__(self, *tyyppi):
                self.tyyppi=tuple(tyyppi)
        def lisaa_tyyppi(self, tyyppi):
                a=list(self.tyyppi)
                a.append(tyyppi)
                self.tyyppi=a
        def on_tyyppia(self, tyyppi):
                return tyyppi in self.tyyppi
        def __str__(self):
                return string.join(
                    map(lambda x: x.__name__, self.tyyppi), ', ')


class Yliluokka:
        def __init__(self):
                self.tyyppi=Luokkatyyppi(Yliluokka)
        def on_tyyppia(self, tyyppi):
                return self.tyyppi.on_tyyppia(tyyppi)
        def tulosta_tyypit(self):
                print 'Tyypit:', self.tyyppi
        def tee(self, k):
                print 'Teenpä jotain',k
        def suorita(self, met, *args):
                if met=='tee':
                        apply(self.tee, args)
                elif met=='tee3':
                        print 'Tee3:',args
                else:
                        print 'Virhe: Metodia',met,\
                           'ei tunnistettu luokassa',\
                           self.__class__.__name__,'!'


class Aliluokka:
        def __init__(self):
                self.yli=Yliluokka()
                self.tyyppi=Luokkatyyppi(Aliluokka, Yliluokka)
        def on_tyyppia(self, tyyppi):
                return self.tyyppi.on_tyyppia(tyyppi)
        def tulosta_tyypit(self):
                print 'Tyypit:', self.tyyppi
        def tee(self, k):
                self.yli.tee(k)
                print 'Teinpä muutakin'
        def suorita(self, met, *args):
                if met=='tee':
                        apply(self.tee, args)
                elif met=='tee2':
                        self.yli.suorita('tee', *args)
                        print 'Teinpä muutakin'
                else:
                        print 'Virhe: Metodia',met,\
                           'ei tunnistettu luokassa',\
                           self.__class__.__name__,\
                           ' yritetään yliluokista...'
                        self.yli.suorita(met, *args)

if __name__=='__main__':
        y=Yliluokka()
        a=Aliluokka()

        print 'Aliluokan tyyppi on:',a.tyyppi
        print

        if a.on_tyyppia(Yliluokka):
                print 'Aliluokka on tyyppiä Yliluokka'
        else:
                print 'Aliluokka ei ole tyyppiä Yliluokka'

        print 'Aliluokka tyyppiä Luokkatyyppi (1=on, 0=ei)?',\
              a.on_tyyppia(Luokkatyyppi)
        print

        print 'ali.tee(23)'
        a.tee(23)
        print

        print "ali.suorita('tee', 23)"
        a.suorita('tee', 23)
        print

        print "ali.suorita('tee2', 23)"
        a.suorita('tee2', 23)
        print

        print "ali.suorita('tee3', 23)"
        a.suorita('tee3', 23)
        print

        print "ali.suorita('tee4', 23)"
        a.suorita('tee4', 23)