Ticket #12953 (closed enhancement: fixed)

Opened 12 months ago

Last modified 12 months ago

Bindable classes

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

Description (last modified by nthiery) (diff)

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

trac_12953_bindable_class-nt.patch Download (8.4 KB) - added by nthiery 12 months ago.

Change History

comment:1 Changed 12 months ago by nthiery

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

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

Changed 12 months ago by nthiery

comment:2 Changed 12 months ago by nthiery

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

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 12 months ago by jdemeyer

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