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)
Change History (9)
Changed 8 years ago by
comment:1 Changed 8 years ago by
- Status changed from new to needs_review
comment:2 Changed 7 years ago by
Please fill in your real name as Author.
comment:3 Changed 7 years ago by
comment:4 Changed 7 years ago by
- 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
- Milestone changed from sage-5.11 to sage-5.12
comment:6 Changed 5 years ago by
- Milestone changed from sage-6.1 to sage-6.2
comment:7 Changed 5 years ago by
- Milestone changed from sage-6.2 to sage-6.3
comment:8 Changed 5 years ago by
- Milestone changed from sage-6.3 to sage-6.4
Add the possibility to rename a lazy attribute