Opened 10 years ago

Closed 10 years ago

#12953 closed enhancement (fixed)

Bindable classes

Reported by: nthiery Owned by: jason
Priority: major Milestone: sage-5.1
Component: misc Keywords: days38
Cc: sage-combinat Merged in: sage-5.1.beta1
Authors: Nicolas M. Thiéry Reviewers: Franco Saliola
Report Upstream: N/A Work issues:
Branch: Commit:
Dependencies: Stopgaps:

Status badges

Description (last modified by nthiery)

From the documentation:

    Bindable classes

    This class implements a binding behavior for nested classes that
    derive from it.

    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 # workaround for python pickling bug
        ...       def f(self, *args):
        ...           print self, args
        ...
        ...       @staticmethod
        ...       def f_static(*args):
        ...           print args
        ...
        ...       class Inner:
        ...           def __init__(self, *args):
        ...               print args
        sage: obj = Outer()

    By default, when Inner is a class nested in Outer, accessing
    ``obj.Inner`` returns the ``Inner`` class as is::

        sage: obj.Inner is Outer.Inner
        True

    In particular, ``obj`` is completely ignored in the following call::

        sage: x = obj.Inner(1,2,3)
        (1, 2, 3)

    This is similar to what happens with a staticmethod::

        sage: obj.f_static(1,2,3)
        (1, 2, 3)

    In some cases, we would want instead Inner to receive ``obj`` as
    parameter, like in a usual method call::

        sage: obj.f(1,2,3)
        <__main__.Outer object at ...> (1, 2, 3)

    To this end, ``obj.f`` returns a *bound method*::

        sage: obj.f
        <bound method Outer.f of <__main__.Outer object at ...>>

    so that ``obj.f(1,2,3)`` is equivalent to::

        sage: Outer.f(obj, 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 # workaround for python pickling bug
        ...
        ...       class Inner(BindableClass):
        ...           " some documentation "
        ...           def __init__(self, obj, *args):
        ...               print obj, args

    Now, ``obj.Inner(1,2,3)`` is equivalent to Outer.Inner(obj, 1,2,3)::

        sage: obj = Outer()
        sage: x = obj.Inner(1,2,3)
        <__main__.Outer object at ...> (1, 2, 3)

This feature will be extensively used for implementing SetsWithRealizations?; see e.g. #12959 and the upcoming NCSF #8899 patch

Attachments (1)

trac_12953_bindable_class-nt.patch (8.4 KB) - added by nthiery 10 years ago.

Download all attachments as: .zip

Change History (4)

comment:1 Changed 10 years ago by nthiery

  • Reviewers set to Franco Saliola
  • Status changed from new to needs_review

For the record: all tests passed for me with 5.0.rc0 and the sage-combinat queue applied up to this patch.

Changed 10 years ago by nthiery

comment:2 Changed 10 years ago by nthiery

  • Description modified (diff)
  • Keywords days38 added
  • Status changed from needs_review to positive_review

On behalf of Franco:

Comment: A variant would be to implement this feature using a class decorator. Practice will tell if we would need that variant. One advantage (or maybe sometimes an inconvenient?) of doing it by inheritance as implemented here is that all subclasses benefit from it, like, e.g., for UniqueRepresentation?.

Positive review!

comment:3 Changed 10 years ago by jdemeyer

  • Merged in set to sage-5.1.beta1
  • Resolution set to fixed
  • Status changed from positive_review to closed
Note: See TracTickets for help on using tickets.