Можно ли переписать метод получения свойства в подклассе? - PullRequest
3 голосов
/ 31 мая 2011

Например:

class Example:
    def __init__(self):
        self.v = 0

    @property
    def value(self):
        return self.v
    @value.setter
    def value(self, v):
        self.v = v

class SubExample(Example):
    pass

Можно ли переписать только значение получателя в значение SubExample?

Ответы [ 3 ]

4 голосов
/ 31 мая 2011

Вы можете сделать это так

class DoubleExample(Example):
    @Example.value.getter
    def value(self):
        return self.v * 2

o = Example()
o.value = 1
print o.value # prints "1"

p = DoubleExample()
p.value = 1
print p.value # prints "2"

Однако это работает, только если Example - это класс нового стиля (class Example(object):), а не класс старого стиля (class Example:), как в коде вашего примера.


Предупреждение: Томас указал в комментариях, что этот метод может работать не так, как ожидается, если вы используете множественное наследование (class Foo(Bar, Baz)).

3 голосов
/ 31 мая 2011

Невозможно переопределить метод получения свойства в подклассе, нет.Свойство - это объект, который живет в классе и содержит ссылки на функции, которые вы ему даете, - если вы позже переопределите имена этих функций, это вообще не повлияет на свойство.

То, что вы можете сделать, это иметь функции, которые вызовы вашего свойства выполняют косвенными вызовами, например:

class Example(object):
    def __init__(self):
        self.v = 0

    @property
    def v(self):
       return self._v_getter()
    @v.setter
    def v(self, value):
       return self._v_setter(value)

    def _v_setter(self, value):
        self._v = value

class SubExample(Example):
    def _v_getter(self):
        return 5

>>> se = SubExample()
>>> se.v
5
>>> se._v
0
>>> se.v = 10
>>> se.v
5
>>> se._v
10

В качестве альтернативы, вы можете переопределить все свойство в подклассе., просто определяя новое свойство.Однако у вас не будет удобного доступа к функциям или свойствам, определенным в родительском классе, и делать правильные вещи перед лицом множественного наследования сложно.

0 голосов
/ 31 мая 2011

На ваш вопрос уже был дан ответ:

http://code.activestate.com/recipes/408713-late-binding-properties-allowing-subclasses-to-ove/ /3957714/problema-pereopredeleniya-svoistva-metoda-python-pochemu-svoistvo-podklassa-prezhnemu-vyzyvaet-metod-bazovogo-klassa

По сути, вместо непосредственного использования property необходимо отложить вызов метода получения, чтобы он получил доступопределенный в подклассе, а не определенный в суперклассе при первом определении свойства.Это может быть достигнуто через lambda:

class Test(object):
    def __init__(self):
        self.v = 0
    def _value(self):
        return self.v
    def _value_setter(self, v):
        self.v = v
    value = property(lambda self: self._value(), lambda self, v: self._value_setter(v))

class Test2(Test):
    def _value(self):
        return self.v + 1

a = Test()
a.value = 2
print a.value  # 2

b = Test2()
b.value = 2
print b.value  # 4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...