Opened 8 years ago

Last modified 5 years ago

#11999 needs_work defect

Renaming lazy attributes

Reported by: SimonKing Owned by: jason
Priority: major Milestone: sage-6.4
Component: misc Keywords:
Cc: nthiery Merged in:
Authors: Simon King Reviewers: Travis Scrimshaw
Report Upstream: N/A Work issues:
Branch: Commit:
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 (1)

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

Download all attachments as: .zip

Change History (9)

Changed 8 years ago by SimonKing

Add the possibility to rename a lazy attribute

comment:1 Changed 8 years ago by SimonKing

  • Status changed from new to needs_review

comment:2 Changed 7 years ago by jdemeyer

Please fill in your real name as Author.

comment:3 Changed 7 years ago by SimonKing

  • Authors changed from Author to Simon King

comment:4 Changed 7 years ago by tscrim

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

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.

comment:5 Changed 6 years ago by jdemeyer

  • Milestone changed from sage-5.11 to sage-5.12

comment:6 Changed 6 years ago by vbraun_spam

  • Milestone changed from sage-6.1 to sage-6.2

comment:7 Changed 6 years ago by vbraun_spam

  • Milestone changed from sage-6.2 to sage-6.3

comment:8 Changed 5 years ago by vbraun_spam

  • Milestone changed from sage-6.3 to sage-6.4
Note: See TracTickets for help on using tickets.