Re: [sage-support] Re: Use lazy_attribute in cython?

2012-05-02 Thread P Purkayastha

On 05/02/2012 03:22 PM, Mike Hansen wrote:

On Wed, May 2, 2012 at 12:08 AM, P Purkayastha  wrote:

Currently, in my Sage (python) code, I used lazy_attribute to achieve this.
I tested the computation using cython and without lazy attribute and it
speeds up by a factor of about 3 compared to the python code. So, I am
looking for something that can defer the computation so that instantiating
the class is fast.


Like Simon mentioned, you can add getattr and setattr support:


from sage.misc.all import lazy_attribute
cdef class A:
cdef public object __dict__
def __init__(self):
self.__dict__ = {}

def __getattr__(self, attr):
try:
return self.__dict__[attr]
except KeyError:
raise AttributeError

def __setattr__(self, attr, value):
self.__dict__[attr] = value

@lazy_attribute
def a(self):
# moderate amount of computation gives the answer 42
return 42

--Mike



Oh! Thanks a lot! This does work!

I thought Simon was explaining the reason why it didn't work. I am just 
vaguely familiar with setattr and getattr, so I didn't think about 
defining them in my own class.


--
To post to this group, send email to sage-support@googlegroups.com
To unsubscribe from this group, send email to 
sage-support+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sage-support
URL: http://www.sagemath.org


Re: [sage-support] Re: Use lazy_attribute in cython?

2012-05-02 Thread Mike Hansen
On Wed, May 2, 2012 at 12:08 AM, P Purkayastha  wrote:
> Currently, in my Sage (python) code, I used lazy_attribute to achieve this.
> I tested the computation using cython and without lazy attribute and it
> speeds up by a factor of about 3 compared to the python code. So, I am
> looking for something that can defer the computation so that instantiating
> the class is fast.

Like Simon mentioned, you can add getattr and setattr support:


from sage.misc.all import lazy_attribute
cdef class A:
   cdef public object __dict__
   def __init__(self):
   self.__dict__ = {}

   def __getattr__(self, attr):
   try:
   return self.__dict__[attr]
   except KeyError:
   raise AttributeError

   def __setattr__(self, attr, value):
   self.__dict__[attr] = value

   @lazy_attribute
   def a(self):
   # moderate amount of computation gives the answer 42
   return 42

--Mike

-- 
To post to this group, send email to sage-support@googlegroups.com
To unsubscribe from this group, send email to 
sage-support+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sage-support
URL: http://www.sagemath.org


Re: [sage-support] Re: Use lazy_attribute in cython?

2012-05-02 Thread P Purkayastha

On 05/02/2012 02:56 PM, Simon King wrote:

Hi!

On 2012-05-02, P Purkayastha  wrote:

--=_Part_843_14196874.1335939956360
Content-Type: text/plain; charset=ISO-8859-1

Is there a way to use lazy_attribute in cython code?


lazy_attribute requires that the object allows attributes to be set.
Thus, it works if you have a non-cdef class (even if the class is
defined in Cython), but I guess you'd need to implement getattr/setattr
support for a cdef class before being able to use it.

Example:

   sage: cython("""
   : from sage.misc.lazy_attribute import lazy_attribute
   : class A:
   : @lazy_attribute
   : def a(self):
   : return "A"
   : cdef class B:
   : @lazy_attribute
   : def b(self):
   : return "B"
   : """)
   sage: a = A()
   sage: b = B()
   sage: a.a
   'A'
   sage: b.b
   ---
   AttributeErrorTraceback (most recent call last)
   ...
   AttributeError: '_home_simon__sage_temp_linux_sqwp_site_5210_tmp_0_' object
   attribute 'b' is read-only

Background: When a lazy attribute L is requested first for an object O, then
L is looked up in O.__class__. It has a __get__ method to bind it to O,
and the __get__ method overrides L in O. Hence, we need that
setattr(O,'L',some_value) works (which doesn't, in the example above).

Best regards,
Simon




Thanks a lot for your answer. What I really need is some kind of lazy 
evaluation. If there is some way to defer an evaluation in cython code, 
then also my objective would be satisfied. Something like this:


cdef class A:
cdef public int a
def __init__(self):
 # is there any way to not evaluate this on init?
self.a = self._get_a()
def _get_a(self):
# moderate amount of computation gives the answer 42
return 42

Currently, in my Sage (python) code, I used lazy_attribute to achieve 
this. I tested the computation using cython and without lazy attribute 
and it speeds up by a factor of about 3 compared to the python code. So, 
I am looking for something that can defer the computation so that 
instantiating the class is fast.


--
To post to this group, send email to sage-support@googlegroups.com
To unsubscribe from this group, send email to 
sage-support+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sage-support
URL: http://www.sagemath.org


[sage-support] Re: Use lazy_attribute in cython?

2012-05-01 Thread Simon King
Hi!

On 2012-05-02, P Purkayastha  wrote:
> --=_Part_843_14196874.1335939956360
> Content-Type: text/plain; charset=ISO-8859-1
>
> Is there a way to use lazy_attribute in cython code?

lazy_attribute requires that the object allows attributes to be set.
Thus, it works if you have a non-cdef class (even if the class is
defined in Cython), but I guess you'd need to implement getattr/setattr
support for a cdef class before being able to use it.

Example:

  sage: cython("""
  : from sage.misc.lazy_attribute import lazy_attribute
  : class A:
  : @lazy_attribute
  : def a(self):
  : return "A"
  : cdef class B:
  : @lazy_attribute
  : def b(self):
  : return "B"
  : """)
  sage: a = A()
  sage: b = B()
  sage: a.a
  'A'
  sage: b.b
  ---
  AttributeErrorTraceback (most recent call last)
  ...
  AttributeError: '_home_simon__sage_temp_linux_sqwp_site_5210_tmp_0_' object
  attribute 'b' is read-only

Background: When a lazy attribute L is requested first for an object O, then
L is looked up in O.__class__. It has a __get__ method to bind it to O,
and the __get__ method overrides L in O. Hence, we need that
setattr(O,'L',some_value) works (which doesn't, in the example above).

Best regards,
Simon


-- 
To post to this group, send email to sage-support@googlegroups.com
To unsubscribe from this group, send email to 
sage-support+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sage-support
URL: http://www.sagemath.org