Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #15578 > unrolled thread
| Started by | Laurent <laurent.payot@gmail.com> |
|---|---|
| First post | 2011-11-10 20:03 -0800 |
| Last post | 2011-11-11 01:41 -0800 |
| Articles | 7 — 4 participants |
Back to article view | Back to comp.lang.python
property decorator and inheritance Laurent <laurent.payot@gmail.com> - 2011-11-10 20:03 -0800
Re: property decorator and inheritance alex23 <wuwei23@gmail.com> - 2011-11-10 20:43 -0800
Re: property decorator and inheritance Laurent <laurent.payot@gmail.com> - 2011-11-10 21:17 -0800
Re: property decorator and inheritance "OKB (not okblacke)" <brenNOSPAMbarn@NObrenSPAMbarn.net> - 2011-11-11 05:54 +0000
Re: property decorator and inheritance Chris Rebert <clp2@rebertia.com> - 2011-11-10 21:58 -0800
Re: property decorator and inheritance Laurent <laurent.payot@gmail.com> - 2011-11-11 01:41 -0800
Re: property decorator and inheritance Laurent <laurent.payot@gmail.com> - 2011-11-11 01:41 -0800
| From | Laurent <laurent.payot@gmail.com> |
|---|---|
| Date | 2011-11-10 20:03 -0800 |
| Subject | property decorator and inheritance |
| Message-ID | <32311626.67.1320984185425.JavaMail.geo-discussion-forums@yqjc16> |
Hi. I couldn't find a way to overwrite a property declared using a decorator in a parent class. I can only do this if I use the "classic" property() method along with a getter function. Here's an example:
#!/usr/bin/python3
class Polite:
def __init__(self):
self._greeting = "Hello"
def get_greeting(self, suffix=", my dear."):
return self._greeting + suffix
greeting1 = property(get_greeting)
@property
def greeting2(self, suffix=", my dear."):
return self._greeting + suffix
class Rude(Polite):
@property
def greeting1(self):
return self.get_greeting(suffix=", stupid.")
@property
def greeting2(self):
return super().greeting2(suffix=", stupid.")
p = Polite()
r = Rude()
print("p.greeting1 =", p.greeting1)
print("p.greeting2 =", p.greeting2)
print("r.greeting1 =", r.greeting1)
print("r.greeting2 =", r.greeting2) # TypeError: 'str' object is not callable
In this example I can easily overwrite the greeting1 property. But the inherited greeting2 doesn't seem to be a property but a mere string.
I use a lot of properties decorators for simple properties in a project and I hate mixing them with a couple of "undecorated" properties that have to be overwritten in child classes. I tried using @greeting2.getter decorator and tricks like this but inheritance overwriting failed every time I used decorators.
Can someone tell me a way to use decorator-declared properties that can be overwritten in child classes?? That would be nice.
[toc] | [next] | [standalone]
| From | alex23 <wuwei23@gmail.com> |
|---|---|
| Date | 2011-11-10 20:43 -0800 |
| Message-ID | <a18d022e-8f1c-46d6-9c5b-b0e6e74a4d3e@l23g2000pro.googlegroups.com> |
| In reply to | #15578 |
On Nov 11, 2:03 pm, Laurent <laurent.pa...@gmail.com> wrote:
> Hi. I couldn't find a way to overwrite a property declared using a decorator in a parent class.
> class Polite:
> @property
> def greeting2(self, suffix=", my dear."):
> return self._greeting + suffix
Here you set up greeting2 as a property.
> class Rude(Polite):
> @property
> def greeting2(self):
> return super().greeting2(suffix=", stupid.")
Here you call Polite.greeting2 as a function.
> print("r.greeting2 =", r.greeting2) # TypeError: 'str' object is not callable
And here it's telling you that you're trying to treat a string - the
output of Polite.greeting2 - as a function.
The problem isn't that you cannot override greeting2 on Rude, it's
that you can't treat properties as functions, so you can't pass in a
new suffix. Instead, break the suffix out as a class attribute, then
each descendent just needs to override that attribute:
class Polite(object):
suffix = ', my dear'
@property
def greeting(self):
return 'Hello' + self.suffix
class Rude(Polite):
suffix = ', stupid'
[toc] | [prev] | [next] | [standalone]
| From | Laurent <laurent.payot@gmail.com> |
|---|---|
| Date | 2011-11-10 21:17 -0800 |
| Message-ID | <33183370.2460.1320988631657.JavaMail.geo-discussion-forums@yqcm23> |
| In reply to | #15582 |
Yes using a separate class variable would transfer the problem to the class level. But adding 10 class variables if I have 10 properties would be ugly. Maybe I should reformulate the subject of this thread to "is there some python magic to pass parameters to decorator-declared properties ?"
[toc] | [prev] | [next] | [standalone]
| From | "OKB (not okblacke)" <brenNOSPAMbarn@NObrenSPAMbarn.net> |
|---|---|
| Date | 2011-11-11 05:54 +0000 |
| Message-ID | <Xns9F99DEFCB64B0OKB@88.198.244.100> |
| In reply to | #15583 |
Laurent wrote:
> Yes using a separate class variable would transfer the problem to
> the class level. But adding 10 class variables if I have 10
> properties would be ugly. Maybe I should reformulate the subject of
> this thread to "is there some python magic to pass parameters to
> decorator-declared properties ?"
You can't have it both ways. If you want
myObj.greeting2 # No parentheses
To evaluate to a string (which it will if it's a property as you
set it up), then it is necessarily true that myObj.greeting2(somearg) is
going to try to call that string, which isn't going to work. If you
need to be able to pass in parameters, then you need greeting2 to be a
real method, not a property, and you need to get the greeting string
with
myObj.greeting2() # Parentheses
All this is as it should be. The whole point of properties is that
outside functions accessing them don't "know" that a getter function is
called behind the scenes.
--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown
[toc] | [prev] | [next] | [standalone]
| From | Chris Rebert <clp2@rebertia.com> |
|---|---|
| Date | 2011-11-10 21:58 -0800 |
| Message-ID | <mailman.2639.1320991104.27778.python-list@python.org> |
| In reply to | #15583 |
On Thu, Nov 10, 2011 at 9:17 PM, Laurent <laurent.payot@gmail.com> wrote:
> Yes using a separate class variable would transfer the problem to the class level. But adding 10 class variables if I have 10 properties would be ugly. Maybe I should reformulate the subject of this thread to "is there some python magic to pass parameters to decorator-declared properties ?"
Apparently, yes:
>>> class Foo(object):
... @property
... def bar(self, arg1='baz', arg2='qux'):
... return arg1, arg2
...
>>> Foo.bar.fget(Foo(), 'spam', 'eggs')
('spam', 'eggs')
>>>
Though I do not like this trick at all.
Cheers,
Chris
--
http://rebertia.com
[toc] | [prev] | [next] | [standalone]
| From | Laurent <laurent.payot@gmail.com> |
|---|---|
| Date | 2011-11-11 01:41 -0800 |
| Message-ID | <mailman.2641.1321004508.27778.python-list@python.org> |
| In reply to | #15586 |
Hey yes it's working that way. But I don't like it very much either. If as OKB said the whole point is that outside functions can't detect a property then I'm going to stick with the non-decorator way. Thanks anyway.
[toc] | [prev] | [next] | [standalone]
| From | Laurent <laurent.payot@gmail.com> |
|---|---|
| Date | 2011-11-11 01:41 -0800 |
| Message-ID | <1571989.1239.1321004499667.JavaMail.geo-discussion-forums@yqpp12> |
| In reply to | #15586 |
Hey yes it's working that way. But I don't like it very much either. If as OKB said the whole point is that outside functions can't detect a property then I'm going to stick with the non-decorator way. Thanks anyway.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web