0

In the code below I would expect that it shouldn't matter if I use the property val or call the function get_val. The output should be the same.

#! /usr/bin/env python

class A():
    def get_val(self):
        print(self)
        raise NotImplementedError

    val = property(get_val)

class B(A):
    def __init__(self):
        self.b_val = "foo\n"

    def get_val(self):
        print(self)
        return self.b_val

b = B()
print(b.get_val())
print(b.val)

But the output I get is:

<__main__.B object at 0x0000014BD2BBE898>
foo

<__main__.B object at 0x0000014BD2BBE898>
Traceback (most recent call last):
  File "prop_override_test.py", line 20, in <module>
    print(b.val)
  File "prop_override_test.py", line 6, in get_val
    raise NotImplementedError
NotImplementedError

Why doesn't the property use the overriden get_val function?

I use python version 3.6.2

python --version
Python 3.6.2
wwii
  • 23,232
  • 7
  • 37
  • 77
j.karlsson
  • 618
  • 4
  • 14
  • 1
    You don't override `val` in `B`, so it still uses `A.val` which is `property(A.get_val)` – user2229219 Jan 13 '18 at 16:38
  • Because `val` is in class A and is bound to A.get_val(). That is, it is bound to a reference to the method, not the name of the method. – cdarke Jan 13 '18 at 16:38
  • 1
    Add `@A.val.getter` as a decorator to the `get_val` method on `B`. – Martijn Pieters Jan 13 '18 at 16:40
  • Because `val` is a class attribute and is evaluated when `A` is *constructed*, so it is bound to `A`'s method.. – wwii Jan 13 '18 at 16:41
  • 1
    Also see [Python overriding getter without setter](//stackoverflow.com/q/15785982) and [What is the purpose of Python's property.getter?](//stackoverflow.com/q/14138580) and [How does the @property decorator work?](//stackoverflow.com/q/17330160) – Martijn Pieters Jan 13 '18 at 16:42

2 Answers2

0

You have to overload the property in B, too:

class A():
    def get_val(self):
        print(self)
        raise NotImplementedError

    val = property(get_val)

class B(A):
    def __init__(self):
        self.b_val = "foo\n"

    def get_val(self):
        print(self)
        return self.b_val

    val = property(get_val)

or since get_val is not really needed, use decorator syntax:

#!/usr/bin/env python

class A():
    @property
    def val(self):
        print(self)
        raise NotImplementedError

class B(A):
    def __init__(self):
        self.b_val = "foo\n"

    @property
    def val(self):
        print(self)
        return self.b_val

b = B()
print(b.val)
Daniel
  • 42,087
  • 4
  • 55
  • 81
-2

The val property is of parent class which is not oveloaded in inerited class. You need to overload it

Advay Umare
  • 432
  • 10
  • 23