Unification of Methods and Functions

Michele Simionato michele.simionato at poste.it
Fri May 14 00:43:30 EDT 2004


David MacQuigg <dmq at gain.com> wrote in message news:<utfh90li0r88p4ea8j1d9891ldm5n4fcki at 4ax.com>...
> 
> ## This does not:
> uf = Cat.talk   # Save an unbound function.
> uf() #=>
> # AttributeError: type object 'Cat' has no attribute 'name'
> 
> I would like to be able to do something like:
> __self__ = cat2
> uf()

So, if I understand correcly, you want Cat.talk to be the same than
cat.talk and Cat to be a prototype just as cat (so Cat must
increase the animal counter and its __init__ method has to
be called at definition time). It is enough to change a
couple of lines in the prototype module:

import sys
from types import FunctionType
from inspect import isfunction

class methodwrapper(object):
    def __init__(self,func,cls):
        self.__func__ = func
        self.__cls__ = cls
    def __get__(self,none,cls):
        globs=sys.modules[cls.__module__].__dict__.copy()
        globs["self"] = globs[cls.__name__] = cls
        globs["super"] = super(self.__cls__,cls)
        return FunctionType(
            self.__func__.func_code,
            globs,
            self.__func__.func_name,
            self.__func__.func_defaults,
            self.__func__.func_closure)

class _Prototype(type):
    def __init__(cls,name,bases,dic):
        for k,v in dic.iteritems():
            if isfunction(v):
                setattr(cls,k,methodwrapper(v,cls))
        super(_Prototype,cls).__init__(name,bases,dic)
        cls.__init__()
    def __call__(cls,*args,**kw):
        newcls = type("Prototype:%s" % cls.__name__,(cls,),
                      {"__module__": cls.__module__}) 
        newcls.__init__(*args,**kw)
        return newcls

class Prototype(object):
    __metaclass__=_Prototype
    def __init__(*args,**kw):
        pass

###  END

Here is an example of usage:

from prototype import Prototype

class Animal(Prototype):  
    numAnimals = 0
    home = "Earth"
    def __init__():
        Animal.numAnimals += 1
    def show():  
        print "Animals:", self.numAnimals

class Feline(Animal):
    genus="Feline"
    def __init__(name="unknown",sound=""):
        super.__init__()
        self.name=name
        self.sound=sound
    def talk():
        print "%s talking: %s!" % (self.genus,self.sound)
        
class Cat(Feline): # created here
    numCats = 0
    def __init__ ( n = "unknown", s = "Meow" ):
        super.__init__(n,s)
        Cat.numCats += 1
    def show():
        super.show()
        print "    Cats:", self.numCats
    def talk():
        print "My name is", self.name
        print "I am a %s from %s" % (self.genus, self.home)
        super.talk()
      
Cat.talk()

cat = Cat("Garfield")
cat.talk()



More information about the Python-list mailing list