Как Вы смешиваете и новый стиль старого стиля классы Python?

Как Jon отмечает, я использую их для обеспечения универсальные операторы с.NET 3.5. Я также использую их (снова в MiscUtil), чтобы предоставить быстрый доступ конструкторам не по умолчанию (Вы не можете использовать Delegate.CreateDelegate с конструкторами, но Expression хорошо работает).

Другое использование вручную созданных деревьев выражений:

, Но действительно, Выражение является очень универсальным способом записать любой динамический код. Намного более простой, чем Reflection.Emit, и за мои деньги, более простые понять, чем CodeDOM. И в.NET 4.0, Вы имеете еще больше опций доступный. Я показываю основные принципы записи кода через Expression на моем блоге .

7
задан cmcginty 15 September 2009 в 19:25
поделиться

1 ответ

Это не проблема смешивания старых и новых классов стилей. super () не вызывает все функции базовых классов, а вызывает первую найденную в соответствии с порядком разрешения метода. В этом случае A2, который, в свою очередь, вызывает A.

Если вы хотите вызвать оба, сделайте это явно:

class C(A2, B2):
   def __init__(self):
      A2.__init__(self)
      B2.__init__(self)
      print 'class C'

Это должно решить эту проблему.

Обновление:

Проблема наследования алмаза, о которой вы говорите, Вопрос в том, какой класс вызывать в ситуации алмазного наследования, например:

class A:
   def method1(self):
      print 'class A'

   def method2(self):
      print 'class A'

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

class C(A):
   def method1(self):
      print 'class C'

   def method2(self):
      print 'class C'

class D(B, C):
   pass

Теперь проверьте это:

>>> D().method1()
'class B'

Это правильно. Он вызывает реализацию первого класса. However, let's try this with method2:

>>> D().method2()
'class A'

Oups, WRONG! It should have called class C.method2() here, because even though class B does not override method2, class C does. Now make class A a newstyle class:

class A(object):
   def method1(self):
      print 'class A'

And try again:

>>> D().method1()
'class B'
>>> D().method2()
'class C'

and hey presto, it works. This is the method resolution order difference between new and old-style classes, and this is what sometimes makes it confusing to mix them.

Notice how at no point both B and C gets called. This is true even if we call super.

class D(B, C):
   def method1(self):
      super(D, self).method1()

   def method2(self):
      super(D, self).method2()

>>> D().method1()
'class B'
>>> D().method2()
'class C'

If you want to call both B and C, you MUST call both explicitly.

Now if you unbreak the diamond, like in your example having separate base classes, the result is different:

class A1(object):
   def method1(self):
      print 'class A1'

   def method2(self):
      print 'class A1'

class A2(object):
   def method1(self):
      print 'class A2'

   def method2(self):
      print 'class A2'

class B(A1):
   def method1(self):
      print 'class B'

class C(A2):
   def method1(self):
      print 'class C'

   def method2(self):
      print 'class C'

class D(B, C):
   def method1(self):
      super(D, self).method1()

   def method2(self):
      super(D, self).method2()


>>> D().method1()
'class B'
>>> D().method2()
'class A1'

This is also per design. Still nowhere two base classes gets called. If you want that to happen you still have to call both explicitly.

6
ответ дан 7 December 2019 в 10:05
поделиться
Другие вопросы по тегам:

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