473,326 Members | 2,124 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

One-Shot Property?


I have many cases in my code where I use a property for calculating a
value on-demand. Quite a few of these only need to be called once.
After that the value is always the same. In these properties, I set a
variable in the instance as a cached value and return that value on
subsequent calls. It would be nice if there was a descriptor that would
do this automatically. Actually, what would be really nice is if I
could replace the property altogether and put the calculated value in
its place after the first call, but the property itself prevents me from
doing that. Is this possible?

--
Kevin Smith
Ke*********@sas.com
Jul 18 '05 #1
6 1532
Kevin Smith wrote:
I have many cases in my code where I use a property for calculating a
value on-demand. Quite a few of these only need to be called once.
After that the value is always the same. In these properties, I set a
variable in the instance as a cached value and return that value on
subsequent calls. It would be nice if there was a descriptor that would
do this automatically. Actually, what would be really nice is if I
could replace the property altogether and put the calculated value in
its place after the first call, but the property itself prevents me from
doing that. Is this possible?


I was going to recommend taking a look at the "memoize" example on the
Python wiki, but it seems to be missing at the moment. In any case,
here's the URL:

http://www.python.org/moin/PythonDecoratorLibrary

There are also a few examples on the Cookbook, like this one:

http://aspn.activestate.com/ASPN/Coo.../Recipe/325205

It shouldn't be too difficult to adapt this technique so that it can be
used to create properties. I wouldn't bother replacing the property with
an attribute unless you have a specific reason to do so (performance,
perhaps).

HTH,
Dave
Jul 18 '05 #2
Kevin Smith wrote:
I have many cases in my code where I use a property for calculating a
value on-demand. Quite a few of these only need to be called once.
After that the value is always the same. In these properties, I set a
variable in the instance as a cached value and return that value on
subsequent calls. It would be nice if there was a descriptor that would
do this automatically. Actually, what would be really nice is if I
could replace the property altogether and put the calculated value in
its place after the first call, but the property itself prevents me from
doing that. Is this possible?


If you use the old-fashioned __getattr__ method instead of properties.
__getattr__ gets called only if the value can't be found in the instance
dictionary.

def __getattr__ (self, attrname):
try:
method = getattr (self, 'calculate_' + attrname)
except AttributeError:
raise AttributeError, attrname
value = method ()
setattr (self, attrname, value)
return value

And probably also through metaclasses. And decorators.

Daniel
Jul 18 '05 #3
Kevin Smith wrote:
I have many cases in my code where I use a property for calculating a
value on-demand. Quite a few of these only need to be called once.
After that the value is always the same. In these properties, I set a
variable in the instance as a cached value and return that value on
subsequent calls. It would be nice if there was a descriptor that would
do this automatically. Actually, what would be really nice is if I
could replace the property altogether and put the calculated value in
its place after the first call, but the property itself prevents me from
doing that.


This should do it:

class CachingProperty(object):
def __init__(self, attr_name, calculate_function):
self._name = attr_name
self._calculate = calculate_function

def __get__(self, obj, type=None):
if obj is None:
return self
else:
value = self._calculate(obj)
setattr(obj, self._name, value)
return value

And example code:
class Foo(object): .... def calculate_value(self):
.... print 'Calculating...'
.... return 42
.... foo = CachingProperty('foo', calculate_value)
.... bar = Foo()
bar.__dict__ {} bar.foo Calculating...
42 bar.foo # Notice that the print statement doesn't run this time 42 bar.__dict__

{'foo': 42}
Jul 18 '05 #4
On Tue, Jan 18, 2005 at 04:54:56PM +0000, Kevin Smith wrote:

I have many cases in my code where I use a property for calculating a
value on-demand. Quite a few of these only need to be called once.
After that the value is always the same. In these properties, I set a
variable in the instance as a cached value and return that value on
subsequent calls. It would be nice if there was a descriptor that would
do this automatically. Actually, what would be really nice is if I
could replace the property altogether and put the calculated value in
its place after the first call, but the property itself prevents me from
doing that. Is this possible?


consider this:

1 >>> class C:
2 ... x = property(str)
3 ...
4 >>> c = C()
5 >>> c.x
6 '<__main__.C instance at 0x4008d92c>'
7 >>> setattr(c, 'x', c.x)
8 >>> c.x
9 '<__main__.C instance at 0x4008d92c>'
10 >>> C.x
11 <property object at 0x4009a7ac>
12 >>> c.x = 2
13 >>>

in line 5 you see that the x property so defined works. In line 7 you
remove it, replacing it with the computed value of the property. Line
9 shows that it worked, line 11 shows that it didn't break the class,
and line 13 (through the absence of an exception) shows that it no
longer is 'special' (as it shouldn't be).

--
John Lenton (jo**@grulic.org.ar) -- Random fortune:
You can tune a piano, but you can't tuna fish.

You can tune a filesystem, but you can't tuna fish.
-- from the tunefs(8) man page

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFB7VZmgPqu395ykGsRApG8AKCWsaaRwbKN8gWCQw2E1g XryWCpZACgrbHz
CjrrwkO6QkZ1ziMG6GKXQug=
=+cST
-----END PGP SIGNATURE-----

Jul 18 '05 #5
Leif K-Brooks wrote:

class CachingProperty(object):
def __init__(self, attr_name, calculate_function):
self._name = attr_name
self._calculate = calculate_function
def __get__(self, obj, type=None):
if obj is None:
return self
else:
value = self._calculate(obj)
setattr(obj, self._name, value)
return value

And example code:
>>> class Foo(object): ... def calculate_value(self):
... print 'Calculating...'
... return 42
... foo = CachingProperty('foo', calculate_value)
... >>> bar = Foo()
>>> bar.__dict__ {} >>> bar.foo Calculating...
42 >>> bar.foo # Notice that the print statement doesn't run this time 42 >>> bar.__dict__

{'foo': 42}

To build on this for Python 2.4:

class Caches(object):
def __init__(self, calculate_function):
self._calculate = calculate_function

def __get__(self, obj, _=None):
if obj is None:
return self
value = self._calculate(obj)
setattr(obj, self._calculate.func_name, value)
return value
class Foo(object):
@Caches
def foo(self):
print 'Calculating...'
return 42

--Scott David Daniels
Sc***********@Acm.Org
Jul 18 '05 #6
On Tuesday 18 January 2005 12:33 pm, John Lenton wrote:

consider this:

1 >>> class C:
2 ... x = property(str)
3 ...
4 >>> c = C()
5 >>> c.x
6 '<__main__.C instance at 0x4008d92c>'
7 >>> setattr(c, 'x', c.x)
8 >>> c.x
9 '<__main__.C instance at 0x4008d92c>'
10 >>> C.x
11 <property object at 0x4009a7ac>
12 >>> c.x = 2
13 >>>

in line 5 you see that the x property so defined works. In line 7 you
remove it, replacing it with the computed value of the property. Line
9 shows that it worked, line 11 shows that it didn't break the class,
and line 13 (through the absence of an exception) shows that it no
longer is 'special' (as it shouldn't be).
It wasn't "special" before, either -- I tried this myself, because I wasn't
familiar with properties yet, and I was trying to figure out what you
meant by that.

The catch is that I think you meant to type:
1 >>> class C(object):


(i.e. so that C is a "new-style" class).

Then we get "special" behavior (which answers my first question):
class C(object): .... x = property(str)
.... C.x <property object at 0x401e8cd4> c = C()
c.x '<__main__.C object at 0x401e984c>' c.x = 2 Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: can't set attribute
Unfortunately this seems to break your technique, too:
setattr(c, 'x', c.x)

Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: can't set attribute

Too bad. I was kind of hoping it was just a typo. :-(

Unless I'm missing something, anyway.

Cheers,
Terry

--
--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com

Jul 18 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: rjl444 | last post by:
I created 2 tables with one to one relationship. if I add a record in table A, how does table B record get created? Does SQL do this automatically because it is one to one relationship? or do I...
5
by: Sami | last post by:
Please bear with me, and if you answer this question, please do it step by step. I am new at Access, not at all sophisticated. I am using Office XP. This will need to be read in Access for...
7
by: Randy Yates | last post by:
I'm a complete newbie to postgres so please look the other way if these questions are really stupid. Is it legitimate to have one database per data file? For organizational and backup purposes,...
44
by: Tolga | last post by:
As far as I know, Perl is known as "there are many ways to do something" and Python is known as "there is only one way". Could you please explain this? How is this possible and is it *really* a...
22
by: petermichaux | last post by:
Hi, I'm curious about server load and download time if I use one big javascript file or break it into several smaller ones. Which is better? (Please think of this as the first time the scripts...
3
by: nasirmajor | last post by:
dear all, a simple quetion for database experts. can three datatables be updated at the same time (from one page)with one table having one primary key and other two tables are having that primary...
2
by: Sky | last post by:
Hello: I'm trying to make sense of snk files, when to use, under what conditions to regenerate new ones,...can someone take a look if these statemes make sense? And then the final questions at the...
32
by: Matias Jansson | last post by:
I come from a background of Java and C# where it is common practise to have one class per file in the file/project structure. As I have understood it, it is more common practice to have many...
25
by: toffee | last post by:
Hi all, apologies if this seems like a pretty basic question - but can an element have more than one class? if so, how do you set them ? and how does the browser give priority to a class over...
1
by: CatchSandeepVaid | last post by:
I have posted this question in hibernate forums also.. As this forum is related to java, i am posting it here also ... In hibernate, presently one-to-one associations are fetched non-lazily... I...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.