Как Jon отмечает, я использую их для обеспечения универсальные операторы с.NET 3.5. Я также использую их (снова в MiscUtil), чтобы предоставить быстрый доступ конструкторам не по умолчанию (Вы не можете использовать Delegate.CreateDelegate
с конструкторами, но Expression
хорошо работает).
Другое использование вручную созданных деревьев выражений:
, Но действительно, Выражение является очень универсальным способом записать любой динамический код. Намного более простой, чем Reflection.Emit
, и за мои деньги, более простые понять, чем CodeDOM. И в.NET 4.0, Вы имеете еще больше опций доступный. Я показываю основные принципы записи кода через Expression
на моем блоге .
Это не проблема смешивания старых и новых классов стилей. 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.