помогите с наследованием питона - PullRequest
1 голос
/ 23 мая 2011

Для произвольного объекта:

class Val(object):
    def __init__(self):
        this_val = 123

Я хочу создать абстрактный базовый класс с атрибутом Val():

class A(object):
    foo = Val()

. Я ожидаю, что когдамои дети наследуют от этого класса, они получат копии Val().Например:

class B(A):
    pass
class C(A):
    pass

Я ожидал бы следующее поведение:

>>> b = B()
>>> c = C()
>>> c.foo.this_val = 456
>>> b.foo.this_val
123

Но вместо этого я получаю:

>>> b.this_val
456

Я понимаю, что мог бы просто self.foo = Val() в init для достижения такого поведения, но у меня есть требование, чтобы foo оставался атрибутом (это менеджер моделей в django).Кто-нибудь может предложить обойти это?

РЕДАКТИРОВАТЬ: Мне действительно нужно иметь возможность получить доступ к значению в качестве атрибута класса, поэтому мое желаемое поведение:

>>> C.foo.this_val = 456
>>> B.foo.this_val
123

Ответы [ 3 ]

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

Атрибут foo только существует в A. Вам нужно будет использовать метакласс, чтобы добавить новый Val в каждый класс.

class Val(object):
    def __init__(self):
        self.this_val = 123

class MC(type):
  def __init__(self, name, bases, d):
    super(MC, self).__init__(name, bases, d)
    self.foo = Val()

class A(object):
  __metaclass__ = MC

class B(A):
  pass

B.foo.this_val = 456
print A.foo.this_val
print B.foo.this_val
2 голосов
/ 23 мая 2011

Может быть, использование дескриптора подойдет вашим требованиям:

class Val(object):
    def __init__(self):
        self.this_val = 123

class ValDesc(object):
    def __init__(self):
        self.cls_lookup = {}

    def __get__(self, obj, objtype=None):
        return self.cls_lookup.setdefault(objtype, Val())

class A(object):
    foo = ValDesc()

class B(A):
    pass
class C(A):
    pass

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

b = B()
c = C()
cc = C()
c.foo.this_val = 456
print c.foo.this_val   # 456
print cc.foo.this_val  # 456
print b.foo.this_val   # 123

РЕДАКТИРОВАТЬ: С редактированием, которое я сделал несколько часов назад, изменив ключ в __get__ наobjtype вместо obj.__class__, это также работает при непосредственном доступе к атрибутам класса:

print B.foo.this_val   # 123
print C.foo.this_val   # 456
0 голосов
/ 23 мая 2011

Выполните оба действия.

Сделайте его атрибутом класса, но также инициализируйте его новым экземпляром в функции __init__.Таким образом, сохраненная ссылка не является общей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...