Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #15578 > unrolled thread

property decorator and inheritance

Started byLaurent <laurent.payot@gmail.com>
First post2011-11-10 20:03 -0800
Last post2011-11-11 01:41 -0800
Articles 7 — 4 participants

Back to article view | Back to comp.lang.python


Contents

  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

#15578 — property decorator and inheritance

FromLaurent <laurent.payot@gmail.com>
Date2011-11-10 20:03 -0800
Subjectproperty 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]


#15582

Fromalex23 <wuwei23@gmail.com>
Date2011-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]


#15583

FromLaurent <laurent.payot@gmail.com>
Date2011-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]


#15585

From"OKB (not okblacke)" <brenNOSPAMbarn@NObrenSPAMbarn.net>
Date2011-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]


#15586

FromChris Rebert <clp2@rebertia.com>
Date2011-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]


#15588

FromLaurent <laurent.payot@gmail.com>
Date2011-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]


#15589

FromLaurent <laurent.payot@gmail.com>
Date2011-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