#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.