Элегантный способ перегрузки свойств класса Python - PullRequest
3 голосов
/ 29 июля 2011

Рассмотрим базовый класс:

class A(object):
   def __init__(self, x):
      self._x = x

   def get_x(self):
      #...
      return self._x

   def set_x(self, x):
      #...
      self._x = x

   x = property(get_x, set_x)

и производный класс:

class B(A):
   def set_x(self, x):
      #...
      self._x = x**2

   x = property(A.get_x, set_x)

Существует ли элегантный способ перегрузки set_x() в классе B, безобъявив это и собственность x?Спасибо.

Ответы [ 2 ]

3 голосов
/ 29 июля 2011

Добавьте дополнительный слой косвенности (то есть используйте хук):

class A(object):
    def __init__(self, x):
        self._x = x

    # Using a _get_hook is not strictly necessary for your problem...
    def _get_hook(self):
        return self._x
    def get_x(self):
        return self._get_hook()

    # By delegating `set_x` behavior to `_set_hook`, you make it possible
    # to override `_set_hook` behavior in subclass B.
    def _set_hook(self, x):
        self._x=x
    def set_x(self, x):
        self._set_hook(x)

    x = property(get_x, set_x)

class B(A):
    def _set_hook(self, x):
        print('got here!')
        self._x = x**2

b=B(5)
b.x=10
# got here!
print(b.x)
# 100

Для современных версий Python вы также можете использовать декоратор @property:

class A(object):

   @property
   def x(self):
      return self._get_hook()

   @x.setter
   def x(self, x):
      self._set_hook(x)
2 голосов
/ 29 июля 2011

Попробуйте это:

 class A(object):
    def __init__(self):
        self._x = 0

    def get_x(self):
        #...
        return self._x

    def set_x(self, x):
        #...
        self._x = x

    x = property(get_x, lambda self,x : self.set_x(x))

class B(A):
    def set_x(self, x):
        #...
        self._x = x**2

Дополнительное косвенное указание лямбды сделает функцию set_x виртуальной.

...