Unbound methods and functions

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ben

    Unbound methods and functions

    Hi,

    I was recently writing a python interpreter (in python), partly to teach
    myself more about the python object system, and partly to learn more about
    how programming languages work in general.

    I started with the getattribute/descriptor system as it seems that this is
    in many ways the "core" of the interpreter, and have come across a few
    questions.

    Firstly, why does the default getattribute first check for data descriptors
    in the type object? Is it only for symmetry with setattr, as it appears to
    me that if you can't set that name in the instance dictionary then the fall
    back to type lookup at the end should always "do the right thing". Of
    course, you could override this by explicitly inserting into the instance
    dictionary (a['foo'] = ...), but in this case it seems that the least
    surprising thing to do would be to return the dictionary version anyway.

    I will post my code so far at the end of this message for people to comment
    on. The other changes that I have made from the python c code is that:

    Object itself contains a lot of the machinery for being a type, and Type
    itself does not do very much.

    dset (the equiv of __set__) returns whether it actually did anything. This
    is becuase I want to reimplement this in c++, and the neatest way I could
    come up with for data descriptors was for the default __set__ to do nothing
    and return false, which means "fall back to inserting into the instance
    dictionary)

    Thanks for the feedback in advance

    Ben
    ---

    Code follows:

    class Object:
    def __init__(self, typeval = None):
    self.dict = {}
    self.typeval = typeval

    def getattribute(se lf, x):
    t = self.lookup(x)
    if t:
    return t.dget(None, self)
    t = self.typeval.lo okup(x)
    if t:
    return t.dget(self, self.typeval)
    raise AttributeError( x)

    def setattribute(se lf, x, val):
    if self.typeval:
    t = self.typeval.lo okup(x)
    if t:
    if t.dset(self, val):
    return
    self.dict[x] = val

    def lookup(self, x):
    for obj in self.mro():
    t = obj.dict.get(x)
    if t:
    return t
    return None

    def mro(self):
    return (self,)

    def dget(self, object, typeval):
    return self

    def dset(self, object, val):
    return False

    def call(self, *args, **kwargs):
    raise TypeError("Not callable")

    class Value(Object):
    def __init__(self, val):
    Object.__init__ (self)
    self.val = val

    class Function(Object ):
    def __init__(self, fun):
    Object.__init__ (self)
    self.fun = fun

    def dget(self, object, typeval):
    if object:
    return BoundFunction(o bject, self)
    else:
    return self

    def call(self, *args, **kwargs):
    return self.fun(*args, **kwargs)

    class BoundFunction(O bject):
    def __init__(self, obj, fun):
    Object.__init__ (self)
    self.fun = fun
    self.obj = obj

    def call(self, *args, **kwargs):
    return self.fun.call(s elf.obj, *args, **kwargs)

    class Type(Object):
    def __init__(self):
    Object.__init__ (self)

    def call(self, *args, **kwargs):
    obj = Object(self)
    return obj

    class Property(Object ):
    def __init__(self, get, set):
    Object.__init__ (self)
    self.get = get
    self.set = set

    def dget(self, object, typeval):
    if object:
    return self.get.call(o bject)
    else:
    return self

    def dset(self, object, val):
    self.set.call(o bject, val)
    return True

    if __name__ == "__main__":
    def addone(self, val):
    return val + 1

    def getfoo(self):
    return self.dict["foo"]

    def setfoo(self, val):
    self.dict["foo"] = val

    test = Type()
    test.setattribu te("b", Value(2))
    test.setattribu te("string", Value("foobar") )
    test.setattribu te("fun", Function(addone ))
    test.setattribu te("getfoo", Function(getfoo ))
    test.setattribu te("setfoo", Function(setfoo ))
    test.setattribu te("foobar", Property(test.g etattribute("ge tfoo"),
    test.getattribu te("setfoo")))

    print test.getattribu te("foobar")

    inst = test.call()
    inst.setattribu te("foobar", Value(2))

    print test.getattribu te("foobar")
    print inst.getattribu te("foobar").va l

    inst.setattribu te("b", Value(3))
    print test.getattribu te("b").val
    print inst.getattribu te("b").val

  • Ben

    #2
    Re: Unbound methods and functions

    Ben wrote:
    [color=blue]
    > Hi,
    >
    > I was recently writing a python interpreter (in python), partly to teach
    > myself more about the python object system, and partly to learn more about
    > how programming languages work in general.
    > ....[/color]

    Arrgh, forgot to ask the question that was the entire point of the post

    Is there any real difference between an unbound method, and a function,
    apart from the scoping differences. I.e would it make any difference in the
    get descriptor for a function, when called on a type, returned the function
    instead of an unbound method?

    Cheers

    Ben
    ---

    Comment

    • Michele Simionato

      #3
      Re: Unbound methods and functions

      Ben <ben@transversa l.com> wrote in message news:<3fc60223$ 0$27468$afc38c8 7@news.easynet. co.uk>...[color=blue]
      >
      > Arrgh, forgot to ask the question that was the entire point of the post
      >
      > Is there any real difference between an unbound method, and a function,
      > apart from the scoping differences. I.e would it make any difference in the
      > get descriptor for a function, when called on a type, returned the function
      > instead of an unbound method?
      >
      > Cheers
      >
      > Ben
      > ---[/color]

      I do not really understand your question. Of course an unbound method
      is different from a function, even if you can convert one in the other.
      For instance, if you are inspecting code (for automatic generation of
      documentation, or for metaprogramming purposes) the two things are
      different: you get one with inspect.isfunct ion, the other with
      inspect.ismetho d. There are other differences too. Look at the source
      code of the inspect module for more. I think you already know the standard
      reference on descriptors:


      Comment

      Working...