change property after inheritance

M

Maric Michaud

Le mercredi 06 septembre 2006 16:33, David Isaac a écrit :
Suppose a class has properties and I want to change the
setter in a derived class. If the base class is mine, I can do this:
http://www.kylev.com/2004/10/13/fun-with-python-properties/
Should I? (I.e., is that a good solution?)

Why not ? This ontroduce the notion of public getter a la C++/Java while the
property is overloadable by itself (as below), but it's correct design IMHO.
And what if I cannot change the base class?
How to proceed then?

Like that :

In [44]: class a(object) :
....: p=property(lambda s : getattr(s, '_p', None))
....:
....:

In [46]: class b(a) :
....: p=property(a.p.fget, lambda s, v : setattr(s, '_p', v))
....:
....:

In [47]: print a().p
None

In [48]: a().p = 5
---------------------------------------------------------------------------
exceptions.AttributeError Traceback (most recent
call last)

/home/maric/<ipython console>

AttributeError: can't set attribute

In [49]: ib=b()

In [50]: print ib.p
None

In [51]: ib.p = 5

In [52]: print ib.p
5

In [53]: ib._p
Out[53]: 5


--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
 
D

David Isaac

Le mercredi 06 septembre 2006 16:33, Alan Isaac a écrit :
Maric Michaud said:
Why not ? This ontroduce the notion of public getter a la C++/Java while the
property is overloadable by itself (as below), but it's correct design
IMHO.

More support for lambda, it seems...
Cheers,
Alan Isaac
 
S

Steven Bethard

David said:
Le mercredi 06 septembre 2006 16:33, Alan Isaac a écrit :


IMHO.

More support for lambda, it seems...

Well, lambda's not going away[1], but there's no *need* for lambda here.
It could be written as::

class Base(object):
def __init__(self):
self.foo = None

def getFoo(self):
return self.__foo

def setFoo(self, val):
self.__foo = val

def _prop_get_foo(self):
return self.getFoo()

def _prop_set_foo(self, val):
return self.setFoo(val)

foo = property(fget=_prop_get_foo, fset=_prop_set_foo)

[1] http://www.python.org/dev/peps/pep-3099/

STeVe
 
G

George Sakkis

Steven said:
David said:
Le mercredi 06 septembre 2006 16:33, Alan Isaac a écrit :


IMHO.

More support for lambda, it seems...

Well, lambda's not going away[1], but there's no *need* for lambda here.
It could be written as::

Sure, it *could*; whether it *should* is a different issue. I can't
imagine a case for absolute *need* of lambda, but there are several
cases where it is probably the best way, such as the one of this
thread.

George
 
S

Steven Bethard

George said:
Steven said:
David said:
Le mercredi 06 septembre 2006 16:33, Alan Isaac a écrit :
Suppose a class has properties and I want to change the
setter in a derived class. If the base class is mine, I can do this:
http://www.kylev.com/2004/10/13/fun-with-python-properties/
Should I? (I.e., is that a good solution?)
Why not ? This ontroduce the notion of public getter a la C++/Java while
the
property is overloadable by itself (as below), but it's correct design
IMHO.

More support for lambda, it seems...
Well, lambda's not going away[1], but there's no *need* for lambda here.
It could be written as::

Sure, it *could*; whether it *should* is a different issue. I can't
imagine a case for absolute *need* of lambda, but there are several
cases where it is probably the best way, such as the one of this
thread.

I'd contend that the "right" solution in this particular case is to use
a descriptor that creates a property with late-binding lookup. That way
you don't even need the extra function call that the lambda is
providing. Try using one of the following recipies:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/408713
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442418

That's not to say that there aren't other situations where a lambda
might be the best solution.

STeVe
 
M

Maric Michaud

Le jeudi 07 septembre 2006 15:33, Steven Bethard a écrit :
Well, lambda's not going away[1],

Sure, they won't.
but there's no *need* for lambda here.
  It could be written as::

Le jeudi 07 septembre 2006 17:16, George Sakkis a écrit :
Sure, it *could*; whether it *should* is a different issue. I can't
imagine a case for absolute *need* of lambda, but there are several
cases where it is probably the best way, such as the one of this
thread.

I have no preferences here, I used lambdas because it's more compact but they
have also their drawback, when the function get a little more complex the
code is quickly confusing. The main advantage of the lambdas in this case is
to not pollute the class namespace.

Le jeudi 07 septembre 2006 23:48, Steven Bethard a écrit :

The code i wrote was to demonstrate late binding is usually not needed (and
it's not the semantic of properties so it's a bit like "make Java in
Python").
Only the second recipe has to do with it, but is not clean IMHO, it's
unnecessary complicated and it introduce a extra level of indentation which
is rather confusing, the 'self' variable in accessors is not what it seems to
be. Moreover, it introduce a new semantic for a functionality which is
already part of the language, what's the goal ? To lost python developers
reading your code ?

If you really want late binding, the first recipe may be a solution, but it
should be both simpler and should not introduce a new semantic (the functions
passed as strings is disappointing).
I'd write it like this :

class LateBindingProperty(property) :
__doc__ = property.__dict__['__doc__'] # see bug #576990

def __init__(self, fget=None, fset=None, fdel=None, doc=None) :
if fget : fget = lambda s, n=fget.__name__ : getattr(s, n)()
if fset : fset = lambda s, v, n=fset.__name__ : getattr(s, n)(v)
if fdel : fdel = lambda s, n=fdel.__name__ : getattr(s, n)()
property.__init__(self, fget, fset, fdel, doc)




In [4]: class A(object) :
...: def getx(self) : return self._x
...: def setx(self, v) : self._x = v
...: p=LateBindingProperty(getx, setx)
...:
...:

In [5]: class B(A) :
...: def setx(self, v) : A.setx(self, 2*v)
...:
...:

In [8]: a=A()

In [9]: a.p = 5

In [10]: a.p
Out[10]: 5

In [11]: a._x
Out[11]: 5

In [12]: b=B()

In [13]: b.p=5

In [14]: b.p
Out[14]: 10

--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
 
S

Steven Bethard

Maric said:
Le jeudi 07 septembre 2006 15:33, Steven Bethard a écrit :
Well, lambda's not going away[1],

Sure, they won't.
but there's no *need* for lambda here.
It could be written as::

Le jeudi 07 septembre 2006 17:16, George Sakkis a écrit :
Sure, it *could*; whether it *should* is a different issue. I can't
imagine a case for absolute *need* of lambda, but there are several
cases where it is probably the best way, such as the one of this
thread.

I have no preferences here, I used lambdas because it's more compact but they
have also their drawback, when the function get a little more complex the
code is quickly confusing. The main advantage of the lambdas in this case is
to not pollute the class namespace.

Le jeudi 07 septembre 2006 23:48, Steven Bethard a écrit :

The code i wrote was to demonstrate late binding is usually not needed (and
it's not the semantic of properties so it's a bit like "make Java in
Python").

If you're really this uncomfortable with writing your own descriptors,
sure, you don't have to. But descriptors are an integral part of Python
-- new-style classes wouldn't have methods without them, nor could
classmethod or staticmethod have been defined. So defining a new
descriptor is far from un-Pythonic.
If you really want late binding, the first recipe may be a solution, but it
should be both simpler and should not introduce a new semantic (the functions
passed as strings is disappointing).

If you want to use the functions instead of their names, it's as simple
as changing the __init__ to:

def __init__(self, fget=None, fset=None, fdel=None, doc=None):
self.getname = fget.__name__
self.setname = fset.__name__
self.delname = fdel.__name__
self.__doc__ = doc

Then you can use the same signature as property.

STeVe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top