Bases: object
Bindable classes
This class implements a binding behavior for nested classes that derive from it. Namely, if a nested class Outer.Inner derives from BindableClass, and if outer is an instance of Outer, then outer.Inner(...) is equivalent to Outer.Inner(outer, ...).
EXAMPLES:
Let us consider the following class Outer with a nested class Inner:
sage: from sage.misc.nested_class import NestedClassMetaclass
sage: class Outer:
... __metaclass__ = NestedClassMetaclass # just a workaround for Python misnaming nested classes
...
... class Inner:
... def __init__(self, *args):
... print args
...
... def f(self, *args):
... print self, args
...
... @staticmethod
... def f_static(*args):
... print args
...
sage: outer = Outer()
By default, when Inner is a class nested in Outer, accessing outer.Inner returns the Inner class as is:
sage: outer.Inner is Outer.Inner
True
In particular, outer is completely ignored in the following call:
sage: x = outer.Inner(1,2,3)
(1, 2, 3)
This is similar to what happens with a static method:
sage: outer.f_static(1,2,3)
(1, 2, 3)
In some cases, we would want instead Inner` to receive outer as parameter, like in a usual method call:
sage: outer.f(1,2,3)
<__main__.Outer object at ...> (1, 2, 3)
To this end, outer.f returns a bound method:
sage: outer.f
<bound method Outer.f of <__main__.Outer object at ...>>
so that outer.f(1,2,3) is equivalent to:
sage: Outer.f(outer, 1,2,3)
<__main__.Outer object at ...> (1, 2, 3)
BindableClass gives this binding behavior to all its subclasses:
sage: from sage.misc.bindable_class import BindableClass
sage: class Outer:
... __metaclass__ = NestedClassMetaclass # just a workaround for Python misnaming nested classes
...
... class Inner(BindableClass):
... " some documentation "
... def __init__(self, outer, *args):
... print outer, args
Calling Outer.Inner returns the (unbound) class as usual:
sage: Outer.Inner
<class '__main__.Outer.Inner'>
However, outer.Inner(1,2,3) is equivalent to Outer.Inner(outer, 1,2,3):
sage: outer = Outer()
sage: x = outer.Inner(1,2,3)
<__main__.Outer object at ...> (1, 2, 3)
To achieve this, outer.Inner returns (some sort of) bound class:
sage: outer.Inner
<bound class '__main__.Outer.Inner' of <__main__.Outer object at ...>>
Note
This is not actually a class, but an instance of functools.partial:
sage: type(outer.Inner).mro()
[<class 'sage.misc.bindable_class.BoundClass'>,
<type 'functools.partial'>,
<type 'object'>]
Still, documentation works as usual:
sage: outer.Inner.__doc__
' some documentation '
TESTS:
sage: from sage.misc.bindable_class import Outer
sage: TestSuite(Outer.Inner).run()
sage: outer = Outer()
sage: TestSuite(outer.Inner).run(skip=["_test_pickling"])
Bases: functools.partial
Bases: sage.misc.bindable_class.BindableClass
Some documentation for Inner2