[Python-Dev] Unbound methods (was: ANNOUNCE: CapPython...)

Mark Seaborn mrs at mythic-beasts.com
Fri Sep 19 20:06:20 CEST 2008


"Guido van Rossum" <guido at python.org> wrote:

> On Thu, Sep 18, 2008 at 2:15 PM, Mark Seaborn <mrs at mythic-beasts.com> wrote:

> > Yes.  The renaming of "im_self" and "im_func" is good.  The removal of
> > unbound methods is a *big* problem [1].
> >
> > Regards,
> > Mark
> >
> > [1] http://lackingrhoticity.blogspot.com/2008/09/cappython-unbound-methods-and-python-30.html
> 
> I don't know to what extent you want to modify Python fundamentals,
> but I think this could be solved simply by adding a metaclass that
> returns an unbound method object for C.f, couldn't it?

I have considered that, and it does appear to be possible to use
metaclasses for that.  It looks like CapPython could set the new
__build_class__ builtin (on a per-module basis), which means that the
verifier would not need to require that every class has a
"metaclass=safemetaclass" declaration.

However, there is a problem which occurs when CapPython code interacts
with normal Python code.

In Python 2.x, CapPython has the very nice property that it is usually
safe to pass normal objects and classes into CapPython code without
allowing the CapPython code to break encapsulation:

 * CapPython code can only use instance objects via their public
   interfaces.
 * If CapPython code receives a class object C, it can create a derived
   class D, but it cannot access private attributes of instances of C
   unless they are also instances of D.  Holding C gives you only limited
   authority: you can only look inside objects whose classes you have
   defined.

There are some builtin objects that are unsafe - e.g. open, getattr,
type - but it is rare for these to be passed around as first class
values.  In constrast, class objects are often passed around to be
used as constructors.

Without unbound methods, normal Python class objects become dangerous
objects.  It becomes much more likely that normal Python code could
accidentally pass a class object in to CapPython code.  So if Python
code defines

class C(object):
    def f(self):
        return self._foo

- then if CapPython code gets hold of C, it can apply C.f(x) to get
x._foo of any object.


I don't really understand the rationale for removing unbound methods.

OK, it simplifies the language slightly.  Sometimes that is good,
sometimes that is bad.

OK, there might occasionally be use cases where you want to define a
function in a class scope and get back the unwrapped function.  But
you can easily get it via the im_func attribute (now __func__).

One of the posts in the original discussion [1] said that removing
unbound methods brings class attributes into line with builtin methods
such as list.append on the grounds that

  list.append is list.__dict__["append"]

is True.  I don't agree: list.append already applies type check:

>>> class C(object): pass
>>> list.append(C(), 1)
TypeError: descriptor 'append' requires a 'list' object but received a 'C'

It has to do so otherwise the interpreter could crash.  The check
added by unbound methods makes class attributes consistent with these
builtins.  Removing unbound methods introduces an inconsistency.

Also, what about the "only one way to do it" principle?  If you want
to define a function that can be applied to any type, there's already
a way to do that: define it outside of a class.

Regards,
Mark

[1] http://mail.python.org/pipermail/python-dev/2005-January/050685.html


More information about the Python-Dev mailing list