#12978: conditionally_defined decorator for methods and nested classes
-------------------------------------------------+-------------------------
       Reporter:  nthiery                        |        Owner:  jason
           Type:  enhancement                    |       Status:  new
       Priority:  major                          |    Milestone:  sage-
      Component:  misc                           |  wishlist
       Keywords:  categories,                    |   Resolution:
  conditionally_defined                          |    Merged in:
        Authors:                                 |    Reviewers:
Report Upstream:  N/A                            |  Work issues:
         Branch:                                 |       Commit:
   Dependencies:                                 |     Stopgaps:
-------------------------------------------------+-------------------------

Comment (by SimonKing):

 With the patch that I just attached, one can do the following:
 {{{
 sage: from sage.misc.conditionally_defined import conditionally_defined
 sage: class C(object):
 ....:     def some_method(self):
 ....:         print "method of C"
 ....:     def __hash__(self):
 ....:         print "hash of C"
 ....:         return int(3)
 ....:
 sage: class D(C):
 ....:     @conditionally_defined(lambda x: x.con>0)
 ....:     def some_method(self):
 ....:         "some doc of some method of D"
 ....:         print "method of D"
 ....:     @conditionally_defined(lambda x: x.con<0)
 ....:     def __hash__(self):
 ....:         "some do of hash of D"
 ....:         print "hash of D"
 ....:         return int(14)
 ....:
 sage: class E(D):
 ....:     @conditionally_defined(lambda x: x.con>0)
 ....:     def further_method(self):
 ....:         "doc of further method"
 ....:         print "no matter what"
 ....:     @conditionally_defined(lambda x: x.con==0)
 ....:     def some_method(self):
 ....:         "this is the doc of some method of E"
 ....:         print "method of E"
 ....:
 sage: x = E()
 sage: y = E()
 sage: z = E()
 sage: x.con = 1
 sage: y.con = -1
 sage: z.con = 0
 }}}

 __"Normal" methods__

 The implementation of `some_method` is correctly chosen, according to the
 value of `.con`:
 {{{
 sage: x.some_method()
 method of D
 sage: y.some_method()
 method of C
 sage: z.some_method()
 method of E
 }}}

 If there is no definition available in the super-class, only the default
 method is used:
 {{{
 sage: x.further_method()
 no matter what
 sage: y.further_method()
 no matter what
 sage: z.further_method()
 no matter what
 }}}

 __Documentation__

 The attribute of the instance is the chosen implementation, thus
 documented accordingly. The documentation of the attribute of the class is
 given by the default implementation, and Sage also adds the documentation
 of the wrapper (I think this is the usual behaviour in Sage):
 {{{
 sage: x.some_method?
 Type:       instancemethod
 String Form:<bound method E.some_method of <__main__.E object at
 0x55dfb10>>
 File:       /home/simon/SAGE/prerelease/sage-5.11.beta3/devel/sage-main
 /<ipython-input-3-a00430d63569>
 Definition: x.some_method(self)
 Docstring:  some doc of some method of D
 sage: y.some_method?
 Type:       instancemethod
 String Form:<bound method E.some_method of <__main__.E object at
 0x55dfb50>>
 File:       /home/simon/SAGE/prerelease/sage-5.11.beta3/devel/sage-main
 /<ipython-input-2-333131ba1041>
 Definition: y.some_method(self)
 Docstring:  x.__init__(...) initializes x; see help(type(x)) for signature
 sage: z.some_method?
 Type:       instancemethod
 String Form:<bound method E.some_method of <__main__.E object at
 0x55df750>>
 File:       /home/simon/SAGE/prerelease/sage-5.11.beta3/devel/sage-main
 /<ipython-input-4-1bdca786a56b>
 Definition: z.some_method(self)
 Docstring:  this is the doc of some method of E
 sage: E.some_method?
 Type:       conditionally_defined
 String Form:Conditionally defined method 'some_method'
 File:
 /home/simon/SAGE/prerelease/sage-5.11.beta3/local/lib/python2.7/site-
 packages/sage/misc/conditionally_defined.so
 Definition: E.some_method(self, meth)
 Docstring:  this is the doc of some method of E

 Class Docstring:
    A wrapper for methods whose definition depends on the state of an
    instance
 Call def:   E.some_method(self, meth)
 sage: D.some_method?
 Type:       conditionally_defined
 String Form:Conditionally defined method 'some_method'
 File:
 /home/simon/SAGE/prerelease/sage-5.11.beta3/local/lib/python2.7/site-
 packages/sage/misc/conditionally_defined.so
 Definition: D.some_method(self, meth)
 Docstring:  some doc of some method of D

 Class Docstring:
    A wrapper for methods whose definition depends on the state of an
    instance
 Call def:   D.some_method(self, meth)
 }}}

 __Special methods__

 The hash is correctly chosen for the instance, according to the value of
 the `.con` attribute:
 {{{
 sage: hash(x)
 hash of C
 3
 sage: hash(y)
 hash of D
 14
 sage: hash(z)
 hash of C
 3
 }}}
 I verified that the hash function is not created repeatedly. In
 particular, changing the value of the `.con ` attribute does not change
 the hash function---a conditional method is fixed once for all:
 {{{
 sage: z.con = -1
 sage: hash(z)
 hash of C
 3
 }}}
 Only when we delete the stored choice of an implementation, the changed
 choice takes effect:
 {{{
 sage: del z.__hash__
 sage: hash(z)
 hash of D
 14
 }}}

 Nicolas, does this sound like a solution to your feature request? Do you
 miss something?

 We should look at timings, in particular for special methods, I should add
 documentation, and then you can review it.

--
Ticket URL: <http://trac.sagemath.org/ticket/12978#comment:10>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to