@KOS_MOS

Разъясните нюанс в наследовании класов в Python?

Есть такой код:

<font color="black"><a href="http://s-c.me/9339/s">Copy&nbsp;Source</a>&nbsp;|&nbsp;<a href="http://s-c.me/9339/h">Copy&nbsp;HTML</a><ol>
<li><font color="#008000">'''</font><br/>
<font color="#008000">Базовый&nbsp;класс</font><br/>
<font color="#008000">'''</font></li>
<li><font color="#0000ff">class</font> <font color="#cc6633">Component</font>():</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;connects = []</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008000">'''</font><br/>
<font color="#008000">&nbsp;&nbsp;&nbsp;&nbsp;Метод&nbsp;добавляе&nbsp;объект&nbsp;в&nbsp;коллекцию</font><br/>
<font color="#008000">&nbsp;&nbsp;&nbsp;&nbsp;'''</font></li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">def</font> <font color="#cc6633">connect</font>(self, object):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>self</b>.connects.append(object)</li>
<li>&nbsp;</li>
<li>&nbsp;</li>
<li><font color="#008000">'''</font><br/>
<font color="#008000">Подкласс&nbsp;1</font><br/>
<font color="#008000">'''</font></li>
<li><font color="#0000ff">class</font> <font color="#cc6633">Component1</font>(<font color="#cc6633">Component</font>):</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">def</font> <font color="#cc6633">getData</font>(self):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">print</font> <font color="#008000">123</font></li>
<li>&nbsp;</li>
<li>&nbsp;</li>
<li><font color="#008000">'''</font><br/>
<font color="#008000">Подкласс&nbsp;2</font><br/>
<font color="#008000">'''</font></li>
<li><font color="#0000ff">class</font> <font color="#cc6633">Component2</font>(<font color="#cc6633">Component</font>):</li>
<li>&nbsp;</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">def</font> <font color="#cc6633">getData</font>(self):</li>
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">print</font> <font color="#008000">123</font></li>
<li>&nbsp;</li>
<li>&nbsp;</li>
<li>&nbsp;</li>
<li><font color="#008000">'''</font><br/>
<font color="#008000">Инстанцируем</font><br/>
<font color="#008000">'''</font></li>
<li>c1 = <font color="#cc6633">Component1</font>()</li>
<li>c2 = <font color="#cc6633">Component2</font>()</li>
<li>&nbsp;</li>
<li><font color="#008000">'''</font><br/>
<font color="#008000">Проверяем&nbsp;кол-во&nbsp;элементов&nbsp;в&nbsp;подклассе&nbsp;2</font><br/>
<font color="#008000">'''</font></li>
<li><font color="#0000ff">print</font> <b>len</b>(<font color="#cc6633">Component2</font>.connects) <font color="#696969">#&nbsp;0</font></li>
<li>&nbsp;</li>
<li><font color="#008000">'''</font><br/>
<font color="#008000">Добавляем&nbsp;первому&nbsp;подклассу&nbsp;в&nbsp;объект&nbsp;коллекцию</font><br/>
<font color="#008000">'''</font></li>
<li>c1.<font color="#cc6633">connect</font>(c2)</li>
<li>&nbsp;</li>
<li><font color="#008000">'''</font><br/>
<font color="#008000">Проверяем&nbsp;кол-во&nbsp;элементов&nbsp;в&nbsp;подклассе&nbsp;2</font><br/>
<font color="#008000">'''</font></li>
<li><font color="#0000ff">print</font> <b>len</b>(<font color="#cc6633">Component2</font>.connects) <font color="#696969">#&nbsp;1&nbsp;</font></li>
</ol></font>



Почему меняется кол-во элементов в коллекции второго объекта, если я добавляю элемент к коллекции первого объекта?
  • Вопрос задан
  • 3672 просмотра
Пригласить эксперта
Ответы на вопрос 3
@shsmad
connects — аттрибут класса Component, не инстанса. Наследующие классы используют ЭТОТ же адрес памяти (id(c1.connects) == id(c2.connects))
Хотите чтоб было разное — добавьте к описанию Component1 и Component2 тоже connects = [], как вы сделали это для базового класса.
Ответ написан
Не
connects = []

а

def __init__(self)
connects = []

PS Отступы парсер съел :(
Ответ написан
qmax
@qmax
программер
а вы уверены, что вам надо коннектить именно к классу, а не к объекту?

тогда правильнее сделать это как @classmethod а не метод объекта.
а чтобы не копировать строчку, атрибут можно создавать в мета-классе:
class MetaComp(type):
  def __init__(cls,name,bases,kwargs):
    super(MetaComp, cls).__init__(name,bases,kwargs)
    cls.connects = [] # для каждого класса и наследника будеит свой

class Comp(object):
  __metaclass__ = MetaComp

  @classmethod
  def connect(cls,obj):
    cls.connects.append(obj)

class Comp1(Comp):
  pass
    
class Comp2(Comp):
  pass

# каждый вызов добавляет к своему connects:
Comp.connect('foo')
Comp1.connect('foo1')
Comp2.connect('foo2')
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы