Ticket #11999 (needs_work defect)

Opened 19 months ago

Last modified 7 months ago

Renaming lazy attributes

Reported by: SimonKing Owned by: jason
Priority: major Milestone: sage-5.10
Component: misc Keywords:
Cc: nthiery Work issues:
Report Upstream: N/A Reviewers: Travis Scrimshaw
Authors: Simon King Merged in:
Dependencies: Stopgaps:

Description

Currently, it is not possible to take an existing lazy attribute and assign it to a different name. The reason is that a lazy attribute overwrites itself by a usual attribute of its __name__. But __name__ is created during initialisation of the lazy attribute. Thus, we have the following example:

sage: class Foo(object):
....:     @lazy_attribute
....:     def _bar(self):
....:         return 5
....:     bar = _bar
....:     
sage: f = Foo()
sage: f.bar  # it seems to work,...
5
sage: f.__dict__['bar'] # ... but the lazy attribute has not become a usual attribute
Traceback (most recent call last):
...
KeyError: 'bar'
sage: f.__dict__['_bar']
5

By consequence, f.bar is much slower than f._bar:

sage: %timeit f.bar
625 loops, best of 3: 2.78 µs per loop
sage: %timeit f._bar
625 loops, best of 3: 185 ns per loop

I suggest to provide lazy attributes with a method rename(), returning a copy of that lazy attribute under a new name.

Example, which is a doc test of my patch:

sage: class Foo(object):
....:     @lazy_attribute
....:     def _bar(self):
....:         return 5
....:     bar = _bar.rename("bar")
....:     
sage: f = Foo()
sage: f.bar
5
sage: f.__dict__['bar']
5
sage: %timeit f.bar
625 loops, best of 3: 184 ns per loop
sage: %timeit f._bar
625 loops, best of 3: 184 ns per loop

Attachments

trac11999_lazy_attribute_rename.patch Download (2.5 KB) - added by SimonKing 19 months ago.
Add the possibility to rename a lazy attribute

Change History

Changed 19 months ago by SimonKing

Add the possibility to rename a lazy attribute

comment:1 Changed 19 months ago by SimonKing

  • Status changed from new to needs_review

comment:2 Changed 10 months ago by jdemeyer

Please fill in your real name as Author.

comment:3 Changed 10 months ago by SimonKing

  • Authors changed from Author to Simon King

comment:4 Changed 7 months ago by tscrim

  • Status changed from needs_review to needs_work
  • Reviewers set to Travis Scrimshaw

I believe you should mention that the renamed name needs to match.

sage: class Foo(object):
....:     @lazy_attribute
....:     def attr(self):
....:         return 5
....:     bar = attr
....:     renamed = attr.rename("renamed")
....:     diffname = attr.rename("renamed")
....:
sage: f = Foo()
sage: f.bar
5
sage: f.attr
5
sage: f.renamed
5
sage: f.diffname
5
sage: %timeit f.bar
625 loops, best of 3: 15.8 µs per loop
sage: %timeit f.attr
625 loops, best of 3: 344 ns per loop
sage: %timeit f.renamed
625 loops, best of 3: 355 ns per loop
sage: %timeit f.diffname
625 loops, best of 3: 23.2 µs per loop
sage: f.__dict__
{'renamed': 5, 'attr': 5}

Additionally please use auto trac linking :trac:`11999` in the doc. Functionally it looks good.

Note: See TracTickets for help on using tickets.