[Python-ideas] CapPython's use of unbound methods

Mark Seaborn mrs at mythic-beasts.com
Thu Mar 12 21:24:10 CET 2009


Guido asked me to explain why the removal of unbound methods in Python
3.0 causes a problem for enforcing encapsulation in CapPython (an
object-capability subset of Python), which I talked about in a blog
post [1].  It also came up on python-dev [2].

Let me try a slightly different example to answer Guido's immediate
question.

Suppose we have an object x with a private attribute, "_field",
defined by a class Foo:

class Foo(object):

    def __init__(self):
        self._field = "secret"

x = Foo()

Suppose CapPython code is handed x.  It should not be able to read
x._field, and the expression x._field will be rejected by CapPython's
static verifier.

However, in Python 3.0, the CapPython code can do this:

class C(object):

    def f(self):
        return self._field

C.f(x) # returns "secret"

Whereas in Python 2.x, C.f(x) would raise a TypeError, because C.f is
not being called on an instance of C.

Guido said, "I don't understand where the function object f gets its
magic powers".

The answer is that function definitions directly inside class
statements are treated specially by the verifier.

If you wrote the same function definition at the top level:

def f(var):
    return var._field # rejected

the attribute access would be rejected by the verifier, because "var"
is not a self variable, and private attributes may only be accessed
through self variables.

I renamed the variable in the example, but the name of the variable
makes no difference to whether it is considered to be a self variable.

Self variables are defined as follows:

If a function definition "def f(v1, ...)" appears immediately within a
"class" statement, the function's first argument, v1, is a self
variable, provided that:
 * the "def" is not preceded by any decorators, and
 * "f" is not read anywhere in class scope and is not declared as global.

The reason for these two restrictions is to prevent the function
object from escaping and being used directly.

Mark

[1] http://lackingrhoticity.blogspot.com/2008/09/cappython-unbound-methods-and-python-30.html
[2] http://mail.python.org/pipermail/python-dev/2008-September/082499.html



More information about the Python-ideas mailing list