Re: inherit without calling parent class constructor?

2005-01-27 Thread Christian Dieterich
On Dé Céadaoin, Ean 26, 2005, at 17:02 America/Chicago, Steven Bethard 
wrote:

Just a note of clarification:
The @deco syntax is called *decorator* syntax.
Classes with a __get__ method are called *descriptors*.
Okay, I think I get the idea. I didn't know about the @deco syntax, but 
it seems to be straightforward. And I got myself updated a little bit 
on descriptors and static methods.

On Dé Céadaoin, Ean 26, 2005, at 17:09 America/Chicago, Jeff Shannon 
wrote:

You could try making D a container for B instead of a subclass:
Thank you for the solution. I'll need to have a closer look at it. 
However it seems like the decision whether to do some expensive 
calculation or not is delegated to the exterior of class D. Different 
classes that instanciate D would need to know what has been going on 
elsewhere. That might complicate things.

I'll go ahead and try with the descriptors first.
Thanks for all the help,
Christian
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-27 Thread Jeff Shannon
Christian Dieterich wrote:
On Dé Céadaoin, Ean 26, 2005, at 17:09 America/Chicago, Jeff Shannon wrote:
You could try making D a container for B instead of a subclass:

Thank you for the solution. I'll need to have a closer look at it. 
However it seems like the decision whether to do some expensive 
calculation or not is delegated to the exterior of class D. Different 
classes that instanciate D would need to know what has been going on 
elsewhere. That might complicate things.
True, in the sense that B is instantiated as soon as a message is sent 
to D that requires B's assistance to answer.  If the decision is a 
case of only calculate this if we actually want to use it, then this 
lazy-container approach works well.  If the decision requires 
consideration of other factors, then it's a bit more complex -- though 
one could write that logic into D, and have D throw an exception (or 
return a sentinel) if it decides not to instantiate B at that time. 
This then requires a bit more checking on the client side, but the 
actual logic is encapsulated in D.

And really, I don't see where the container approach shifts the 
decision any more than the descriptor approach does.  In either case, 
the calculation happens as soon as someone requests D.size ...

(However, from your other descriptions of your problem, it does sound 
like a property / descriptor is a better conceptual fit than a 
contained class is.  I mostly wanted to point out that there are other 
ways to use OO than inheritance...)

Jeff Shannon
Technician/Programmer
Credit International
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-27 Thread Christian Dieterich
On Déardaoin, Ean 27, 2005, at 14:05 America/Chicago, Jeff Shannon 
wrote:

True, in the sense that B is instantiated as soon as a message is sent 
to D that requires B's assistance to answer.  If the decision is a 
case of only calculate this if we actually want to use it, then this 
lazy-container approach works well.  If the decision requires
Yes, I see this advantage of a lazy container. Seems perfect to do 
something on request. See also below.

the descriptor approach does.  In either case, the calculation happens 
as soon as someone requests D.size ...
Agreed. The calculation happens as soon as someone requests D.size. So 
far so good. Well, maybe I'm just not into it deep enough. As far as I 
can tell, In your class D the calculation happens for every 
instantiation of D, right? For my specific case, I'd like a construct 
that calculates D.size exactly once and uses the result for all 
subsequent instantiations.

If it will work for numerous D instances to share a single B instance 
(as one of your workarounds suggests), then you can give D's 
__init__() a B parameter that defaults to None.
This sounds as if B needs to instantiated only once. In your example 
self._B is None for every new instantiation of D and then __getattr__() 
makes a new instances of self.B.

(However, from your other descriptions of your problem, it does sound 
like a property / descriptor is a better conceptual fit than a 
contained class is.  I mostly wanted to point out that there are other 
ways to use OO than inheritance...)
I appreciate your input anyway. Thinking of how I could use containers 
it became clear, that I'm going to use them for something else, where I 
want something to be calculated upon request only.

Christian
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-27 Thread Jeff Shannon
Christian Dieterich wrote:
On Déardaoin, Ean 27, 2005, at 14:05 America/Chicago, Jeff Shannon wrote:
 
the descriptor approach does.  In either case, the calculation happens 
as soon as someone requests D.size ...
Agreed. The calculation happens as soon as someone requests D.size. So 
far so good. Well, maybe I'm just not into it deep enough. As far as I 
can tell, In your class D the calculation happens for every 
instantiation of D, right? For my specific case, I'd like a construct 
that calculates D.size exactly once and uses the result for all 
subsequent instantiations.
Okay, so size (and the B object) is effectively a class attribute, 
rather than an instance attribute.  You can do this explicitly --

class D(object):
_B = None
def __getattr__(self, attr):
if self._B is None:
if myB is None:
myB = B()
D._B = myB
return getattr(self._B, attr)
Now, when the B object is first needed, it's created (triggering that 
expensive calculation) and stored in D's class object.  Since all 
instances of D share the class object, they'll all share the same 
instance of B.

Probably not worth the trouble in this particular case, but maybe in 
another case... :)

Jeff Shannon
Technician/Programmer
Credit International
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-27 Thread Christian Dieterich
On Déardaoin, Ean 27, 2005, at 19:25 America/Chicago, Jeff Shannon 
wrote:

Okay, so size (and the B object) is effectively a class attribute, 
rather than an instance attribute.  You can do this explicitly --
Ah, now I'm getting there. That does the trick.
Probably not worth the trouble in this particular case, but maybe in 
another case... :)
Yeah, maybe not. But I'll remember it as a useful recipe.
Cheers,
Christian
--
http://mail.python.org/mailman/listinfo/python-list


inherit without calling parent class constructor?

2005-01-26 Thread Christian Dieterich
Hi,
I need to create many instances of a class D that inherits from a class 
B. Since the constructor of B is expensive I'd like to execute it only 
if it's really unavoidable. Below is an example and two workarounds, 
but I feel they are not really good solutions. Does somebody have any 
ideas how to inherit the data attributes and the methods of a class 
without calling it's constructor over and over again?

Thank,
Christian
Here's the proper example:
class B:
def __init__(self, length):
size = self.method(length)
self.size = size
def __str__(self):
return 'object size = ' + str(self.size)
def method(self, length):
print 'some expensive calculation'
return length
class D(B):
def __init__(self, length):
B.__init__(self, length)
self.value = 1
if __name__ == __main__:
obj = D(7)
obj = D(7)
Here's a workaround:
class B:
def __init__(self, length):
size = self.method(length)
self.size = size
def __str__(self):
return 'object size = ' + str(self.size)
def method(self, length):
print 'some expensive calculation'
return length
class D(B):
def __init__(self, object):
for key, value in object.__dict__.iteritems():
setattr(self, key, value)
self.value = 1
if __name__ == __main__:
tmp = B(7)
obj = D(tmp)
obj = D(tmp)
Here's another workaround:
Bsize = 0
class B:
def __init__(self, length):
size = self.method(length)
self.size = size
global Bsize
Bsize = self.size
def __str__(self):
return 'object size = ' + str(self.size)
def method(self, length):
print 'some expensive calculation'
return length
class D(B):
def __init__(self, length):
self.size = Bsize
self.value = 1
if __name__ == __main__:
B(7)
obj = D(9)
obj = D(9)
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-26 Thread Steven Bethard
Christian Dieterich wrote:
Hi,
I need to create many instances of a class D that inherits from a class 
B. Since the constructor of B is expensive I'd like to execute it only 
if it's really unavoidable. Below is an example and two workarounds, but 
I feel they are not really good solutions. Does somebody have any ideas 
how to inherit the data attributes and the methods of a class without 
calling it's constructor over and over again?

Thank,
Christian
Here's the proper example:
class B:
def __init__(self, length):
size = self.method(length)
self.size = size
def __str__(self):
return 'object size = ' + str(self.size)
def method(self, length):
print 'some expensive calculation'
return length
class D(B):
def __init__(self, length):
B.__init__(self, length)
self.value = 1
if __name__ == __main__:
obj = D(7)
obj = D(7)
I'm confused as to how you can tell when it's avoidable...  Do you mean 
you don't want to call 'method' if you don't have to?  Could you make 
size a property, e.g.

class B(object):
def __init__(self, length):
self._length = length
def _get_size(self):
print 'some expensive calculation'
return self._length
size = property(fget=_get_size)
class D(B):
def __init__(self, length):
super(B, self).__init__(length)
self.value = 1
if __name__ == __main__:
obj = D(7)
obj = D(7)
Then 'size' won't be calculated until you actually use it.  If 'size' is 
only to be calculated once, you might also look at Scott David Daniels's 
lazy property recipe:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/363602
Steve
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-26 Thread Daniel Dittmar
Christian Dieterich wrote:
I need to create many instances of a class D that inherits from a class 
B. Since the constructor of B is expensive I'd like to execute it only 
if it's really unavoidable. Below is an example and two workarounds, but 
I feel they are not really good solutions. Does somebody have any ideas 
how to inherit the data attributes and the methods of a class without 
calling it's constructor over and over again?
- rename B to A
- class B (A)
- move the costly constructor from A to B
- class D (A)
You can now move some parts from B.__init__ to A.__init__ if they are 
really needed by D as well.

In OO speak: D is not really a subclass of B. Refactor the common code 
into a new class A.

Daniel
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-26 Thread Christian Dieterich
On Dé Céadaoin, Ean 26, 2005, at 11:46 America/Chicago, Steven Bethard 
wrote:

I'm confused as to how you can tell when it's avoidable...  Do you 
mean you don't want to call 'method' if you don't have to?  Could you 
make size a property, e.g.

Then 'size' won't be calculated until you actually use it.  If 'size' 
is only to be calculated once, you might also look at Scott David 
Daniels's lazy property recipe:
On Dé Céadaoin, Ean 26, 2005, at 12:03 America/Chicago, Daniel Dittmar 
wrote:

- rename B to A
- class B (A)
- move the costly constructor from A to B
- class D (A)
You can now move some parts from B.__init__ to A.__init__ if they are 
really needed by D as well.
Thanks for the input.
Yes, I see. I should have been more specific about 'when it's 
avoidable'. I guess this was part of my question: Is it avoidable?

Steven, your solution works fine, as long as I don't access the size 
attribute. However,
my instances of A use their size attributes quite often within other 
methods of A (not listed in my example). So, I'd just postpone the 
execution of the expensive part until later.

Daniel, maybe I should have made it clearer in my example. The 
A-objects actually need the size attribute. If I'd outsource the size 
attribute (and its computation) to a class I don't inherit from, the 
A-objects won't have access to it. Or did I miss something in your 
solution?

The size attribute only needs to be computed once and stays constant 
after that. The lazy property recipe of Scott David Daniels looks 
promising. I'll try that, when I've installed Python 2.4. However, I 
need my package to work on machines where there is Python 2.2 and 2.3 
only.

Thanks for more ideas,
Christian
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-26 Thread Steven Bethard
Christian Dieterich wrote:
The size attribute only needs to be computed once and stays constant 
after that. The lazy property recipe of Scott David Daniels looks 
promising. I'll try that, when I've installed Python 2.4. However, I 
need my package to work on machines where there is Python 2.2 and 2.3 only.
Note that:
@deco
def func(...):
...
is basically just syntactic sugar for:
def func(...):
...
func = deco(func)
So you don't need 2.4 to use the recipe; you just need a version of 
Python that supports descriptors (2.2 or later) since the recipe uses a 
class with __get__.  I believe the following code should work for Python 
2.2 and later, though I only have 2.4 to test it on at home.

py class LazyAttribute(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
...
py class B(object):
... def __init__(self, length):
... self._length = length
... def size(self):
... print 'some expensive calculation'
... return self._length
... size = LazyAttribute(size)
...
py class D(B):
... def __init__(self, length):
... super(D, self).__init__(length)
... self.value = 1
...
py b = B(5)
py b.size
some expensive calculation
5
py b.size
5
py d = D(6)
py d.size
some expensive calculation
6
py d.size
6
Note that b.size and d.size are only calculated once each, and if d.size 
is never accessed, you'll never incur the costs of calculating it.

Steve
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-26 Thread Christian Dieterich
On Dé Céadaoin, Ean 26, 2005, at 13:45 America/Chicago, Steven Bethard 
wrote:

Note that:
@deco
def func(...):
...
is basically just syntactic sugar for:
def func(...):
...
func = deco(func)
Oh, I learned something new today :-) Nice thing to know, these 
descriptors.

Note that b.size and d.size are only calculated once each, and if 
d.size is never accessed, you'll never incur the costs of calculating 
it.
That's exactly what I need. It works fine for Python 2.2 and 2.3. So, 
I'll try to implement that into my package.

Thanks a bunch for your help,
Christian
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-26 Thread Steven Bethard
Christian Dieterich wrote:
On Dé Céadaoin, Ean 26, 2005, at 13:45 America/Chicago, Steven Bethard 
wrote:

Note that:
@deco
def func(...):
...
is basically just syntactic sugar for:
def func(...):
...
func = deco(func)

Oh, I learned something new today :-) Nice thing to know, these 
descriptors.
Just a note of clarification:
The @deco syntax is called *decorator* syntax.
Classes with a __get__ method are called *descriptors*.
But yes, they're both nice things to know. ;)
Steve
--
http://mail.python.org/mailman/listinfo/python-list


Re: inherit without calling parent class constructor?

2005-01-26 Thread Jeff Shannon
Christian Dieterich wrote:
Hi,
I need to create many instances of a class D that inherits from a class 
B. Since the constructor of B is expensive I'd like to execute it only 
if it's really unavoidable. Below is an example and two workarounds, but 
I feel they are not really good solutions. Does somebody have any ideas 
how to inherit the data attributes and the methods of a class without 
calling it's constructor over and over again?
You could try making D a container for B instead of a subclass:
class D(object):
def __init__(self, ...):
self._B = None
def __getattr__(self, attr):
if self._B is None:
self._B = B()
return getattr(self._B, attr)
Include something similar for __setattr__(), and you should be in 
business.

If it will work for numerous D instances to share a single B instance 
(as one of your workarounds suggests), then you can give D's 
__init__() a B parameter that defaults to None.

Jeff Shannon
Technician/Programmer
Credit International
--
http://mail.python.org/mailman/listinfo/python-list