M
Michele Simionato
So far, I have not installed Prothon, nor I have experience with Io, Self
or other prototype-based languages. Still, from the discussion on the
mailing list, I have got the strong impression that you do not actually
need to fork Python in order to implement prototypes. It seems to me
that Python metaclasses + descriptors are more than powerful enough to
implementing prototypes in pure Python.
I wrote a module that implements part of what David MacQuigg discussed in
http://apache.ece.arizona.edu/~edatools/Python/Prototypes.htm in few lines
of code (disclaimer: this is an horrible hack that changes Python semantics
and makes "super" and "self" kinda of implicit reserved
keywords, highly unpythonic). It requires Python 2.2+.
I have not read the whole David MacQuigg's document, nor I have done any
serious testing of the module, nor I claim I do understand what prototypes
are; also I guarantee there will be bugs and surprising behaviors, but
still I think they could be fixed if I was willing to spend more time
on the issue.
Here is an example of usage:
from prototype import Prototype # prototypes are implemented as classes
class Animal(Prototype):
numAnimals = 0
home = "Earth"
def __init__(): # no need to pass self around
Animal.numAnimals += 1
def show():
print "Animals:", self.numAnimals
class Feline(Animal):
genus="Feline"
def __init__(name,sound): # no need to pass self around
super.__init__()
self.name=name
self.sound=sound
def talk(): # no need to pass self around
print "%s talking: %s!" % (self.genus,self.sound)
class Cat(Feline): # how to call the super prototype
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()
cat1 = Cat() # abuse of notation: makes a new prototype, not an instance
print cat1 # =>
# <class '__main__.Prototype:Cat'>
cat2 = Cat("Garfield")
cat2.home = "Tucson"
print cat2 # =>
# <class '__main__.Prototype:Cat'>
cat1.talk() # =>
# My name is unknown
# I am a Feline from Earth
# Feline talking: Meow!
cat2.talk()# =>
# My name is Garfield
# I am a Feline from Tucson
# Feline talking: Meow!
cat2.show() # =>
# Animals: 2
# Cats: 2
I am not sure this does what prototype people wants, but still it is
a nice example of how to abuse Python Originally, I tried to use
"_" for "self" and "__" for "super", but with my fonts it was
difficult to distinguish between them. With a preprocessor one
could replace .name -> self.name and ..name -> super.name, but
I did no bother to do that.
Here is the module (not at all optimized):
$ cat prototype.py
import sys
from types import FunctionType
from inspect import isfunction
class methodwrapper(object): # descriptor
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"]=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): # metaclass
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)
def __call__(cls,*args,**kw):
newcls = type("Prototype:%s" % cls.__name__,(cls,),
{"__module__": cls.__module__})
newcls.__init__(*args,**kw)
return newcls
class Prototype(object): # mother of all prototypes
__metaclass__=_Prototype
def __init__(*args,**kw):
pass
#### END ####
Michele Simionato
or other prototype-based languages. Still, from the discussion on the
mailing list, I have got the strong impression that you do not actually
need to fork Python in order to implement prototypes. It seems to me
that Python metaclasses + descriptors are more than powerful enough to
implementing prototypes in pure Python.
I wrote a module that implements part of what David MacQuigg discussed in
http://apache.ece.arizona.edu/~edatools/Python/Prototypes.htm in few lines
of code (disclaimer: this is an horrible hack that changes Python semantics
and makes "super" and "self" kinda of implicit reserved
keywords, highly unpythonic). It requires Python 2.2+.
I have not read the whole David MacQuigg's document, nor I have done any
serious testing of the module, nor I claim I do understand what prototypes
are; also I guarantee there will be bugs and surprising behaviors, but
still I think they could be fixed if I was willing to spend more time
on the issue.
Here is an example of usage:
from prototype import Prototype # prototypes are implemented as classes
class Animal(Prototype):
numAnimals = 0
home = "Earth"
def __init__(): # no need to pass self around
Animal.numAnimals += 1
def show():
print "Animals:", self.numAnimals
class Feline(Animal):
genus="Feline"
def __init__(name,sound): # no need to pass self around
super.__init__()
self.name=name
self.sound=sound
def talk(): # no need to pass self around
print "%s talking: %s!" % (self.genus,self.sound)
class Cat(Feline): # how to call the super prototype
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()
cat1 = Cat() # abuse of notation: makes a new prototype, not an instance
print cat1 # =>
# <class '__main__.Prototype:Cat'>
cat2 = Cat("Garfield")
cat2.home = "Tucson"
print cat2 # =>
# <class '__main__.Prototype:Cat'>
cat1.talk() # =>
# My name is unknown
# I am a Feline from Earth
# Feline talking: Meow!
cat2.talk()# =>
# My name is Garfield
# I am a Feline from Tucson
# Feline talking: Meow!
cat2.show() # =>
# Animals: 2
# Cats: 2
I am not sure this does what prototype people wants, but still it is
a nice example of how to abuse Python Originally, I tried to use
"_" for "self" and "__" for "super", but with my fonts it was
difficult to distinguish between them. With a preprocessor one
could replace .name -> self.name and ..name -> super.name, but
I did no bother to do that.
Here is the module (not at all optimized):
$ cat prototype.py
import sys
from types import FunctionType
from inspect import isfunction
class methodwrapper(object): # descriptor
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"]=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): # metaclass
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)
def __call__(cls,*args,**kw):
newcls = type("Prototype:%s" % cls.__name__,(cls,),
{"__module__": cls.__module__})
newcls.__init__(*args,**kw)
return newcls
class Prototype(object): # mother of all prototypes
__metaclass__=_Prototype
def __init__(*args,**kw):
pass
#### END ####
Michele Simionato