2013-06-12 4 views
4
class A: 
    def __init__(self): 
     print 'A' 


class B(A): 
    def __init__(self): 
     print 'B' 


b = B() 
B 

В C++ я бы ожидал увидеть вывод A B, но в Python я получаю только B. Я знаю, что могу сделать super(B, self).__init__(), чтобы добиться того же самого в Python, но поскольку это, по-видимому, не является значением по умолчанию (или оно - я новичок в синтаксисе), я обеспокоен тем, что парадигмы для создания объектов полностью разные.Почему родительские конструкторы не вызываются при создании экземпляра класса?

Итак, какие объекты в Python, какова их связь с классами и каков стандартный способ инициализации всех данных во всех родительских классах в Python?

+2

Помните, что 'super' работает только с классами нового стиля, которые происходят из' object'. –

ответ

2

Итак, какие объекты в Python

Ну, объекты в Python, как словари членов и методов. Это не сложнее, чем это. У вас нет обработки видимости (если вы хотите скрыть участника, просто не говорите об этом в публичной документации, только с комментарием).

какова их связь с классами

Класс определяет скелет метод/элемента, который будет создать экземпляр этого ДИКТ/объект. Таким образом, вы получили конструктор __init__(), который является только обработчиком, используемым при создании этого объекта.

Что такое стандартный способ инициализации всех данных во всех родительских классах в Python?

Либо вы не переопределить конструктор, а затем все родительские классы будут иметь их конструктор инициировал (например, поведение по умолчанию C++) или вы переопределить конструктор, а затем сделать явный вызов вашего родительского класса конструктор.

Помните дзен python: «Явный лучше, чем неявный». Это полностью применимо здесь.

1

Вам нужно вызвать базовый конструктор в вашем унаследованного конструктора класса:

class B(A): 
    def __init__(self): 
     A.__init__(self) 
     # super(B, self).__init__() you can use this line as well 
     print 'B' 
4

Python редко делает что-либо автоматически. Как вы говорите, если вы хотите, чтобы вызвать суперкласс __init__, то вам нужно сделать это самостоятельно, как правило, по телефону super:

class B(A): 
    def __init__(self): 
     print 'B' 
     super(B, self).__init__() 

точки следует отметить, что атрибуты экземпляра, как и все остальное в Python, являются динамическими , __init__ не является конструктором, то есть __new__, с которым вам редко приходится вмешиваться. Объект полностью сконструирован к моменту, когда вызывается __init__, но поскольку атрибуты экземпляра являются динамическими, они обычно добавляются этим методом, что является особенным только тем, что он вызывается первым, когда объект создается.

Вы можете, конечно, создать атрибуты экземпляра любым другим способом или даже вне класса, просто сделав что-то вроде myBobj.foo = 'bar'.

+1

'super()' работает только для классов нового стиля, поэтому ваш код будет работать, только если 'A' объявлен' class A (object): '.В коде OP это просто 'class A:'. Кроме того, чтобы избежать имен hardcoding в подклассах, я предпочитаю писать 'super (self .__ class__, self) .__ init __()', который будет работать независимо от имени подкласса. – martineau

+2

@martineau не * всегда * делаю, принципиально сломан. В цепочке наследования 'self .__ class__' всегда ссылается на самый нижний класс: если вы вызываете super on' self .__ class__' в середине цепочки, он будет ссылаться на родительский элемент нижнего подкласса и будет поэтому застряли в бесконечном цикле. –

+0

Хорошая точка. Итак, нет хорошего способа избежать использования фактического имени подкласса в вызове 'super()'? – martineau

Смежные вопросы