
On Thu, Mar 12, 2009 at 1:24 PM, Mark Seaborn <mrs@mythic-beasts.com> wrote:
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()
Can you add some principals to this example? Who wrote the Foo class definition? Does CapPython have access to the source code for Foo? To the class object?
Suppose CapPython code is handed x.
What does it mean to "hand x to CapPython"? Who "is" CapPython?
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.
In Python 2.x I could write class C(Foo): def f(self): return self._field or alternatively class C(x.__class__): <same f as before>
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.
Hm, this sounds like a major change in language semantics, and if I were Sun I'd sue you for using the name "Python" in your product. :-)
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,
What do you mean by this?
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.
Do you also catch things like g = getattr s = 'field'.replace('f', '_f') print g(x, s) ?
Mark
[1] http://lackingrhoticity.blogspot.com/2008/09/cappython-unbound-methods-and-p... [2] http://mail.python.org/pipermail/python-dev/2008-September/082499.html
-- --Guido van Rossum (home page: http://www.python.org/~guido/)