2016-05-19 1 views
0

Позволяет есть примерOverride внутренний класс

class A: 
    class B: 
     def f(self): 
      return 1 
    def a(self): 
     return A.B().f() 
    def b(self): 
     return self.B().f() 

class C(A): 
    class B(A.B): 
     def f(self): 
      return 2 

print(A().a()) 
print(A().b()) 
print(C().a()) 
print(C().b()) 

произведут

1 
1 
1 
2 

Я хочу сделать что-то, что он производит

1 
1 
2 
2 

Как я могу переопределить класс А, так что оба метода, a и b возвращают 2?
Я работаю с сгенерированным кодом с antlr. То, что я хочу сделать, - это, например, переопределить методы __str __(), чтобы получить более качественную информацию. Он продолжает генерировать код, например MyLanguageParser.RootContext() вместо self.RootContext(), и теперь я хочу переопределить все, что мне нужно, чтобы справиться с кодом методов, где вызываются классы.
Есть ли у вас какие-либо решения? Я знаю, что я еще не лучший с Python.
Возможно, это невозможно, и решение заключается в изменении сгенерированного кода, но я слышал, что это очень плохая идея.
Edit:
Класс A генерируется и неизменен
То, что я думал, что это что-то вроде

A.B = C.B 
print(A().a()) 
print(A().b()) 
print(C().a()) 
print(C().b()) 

сгенерирует

2 
2 
2 
2 

Я не знаю, если это законно. На самом деле я не буду использовать класс A, но остальная часть сгенерированного кода может его использовать. Я не знаю, безопасно ли это. Edit 2: Исправлена ​​ошибка с отсутствием самости

+0

Вам необходимо изменить способ генерации кода или переопределить 'a' и' b' вместо 'B'. – user2357112

+0

позволяет сказать, что класс A сгенерирован и неизменен. –

+0

Это просто означает, что вы меняете вещи, которые управляют его поколением, а не редактируют сгенерированный код напрямую. – user2357112

ответ

1

возможно:

class A: 
    class B: 
     def f(self): 
      return 1 
    def a(self): 
     # `type(self)` here instead of `A` 
     # to get actual `C` class instead of `A` 
     # when `a()` calls for `C()` 
     return type(self).B().f() 
    def b(self): 
     return self.B().f() 

class C(A): 
    class B(A.B): 
     def f(self): 
      return 2 

Или без необходимости модифицировать A:

class A: 
    class B: 
     def f(self): 
      return 1 
    def a(self): 
     return A.B().f() 
    def b(self): 
     return self.B().f() 


class C(A): 
    class B(A.B): 
     def f(self): 
      return 2 

    def a(self): # reimplement 
     return type(self).B().f() 

Или каким-то образом пытается переписать A динамически, чтобы избежать перезаписи a Код:

class A: 
    class B: 
     def f(self): 
      return 1 
    def a(self): 
     return A.B().f() 
    def b(self): 
     return self.B().f() 


class C(A): 
    class B(A.B): 
     def f(self): 
      return 2 

    def a(self): 
     tmp, globals()['A'] = A, type(self) 
     try: 
      return super().a() 
     finally: 
      globals()['A'] = tmp 

Примечание. Это может быть плохая идея. Я бы подумал, что есть лучший способ.

+0

Я не могу изменить A, как это, дается A. Что я могу сделать, это изменить C или сделать sth как A.B = C.B, но он произведет 2 2 2 2 вместо 1 1 2 2 –

+0

@ MichałPiotrStankiewicz Я обновил ответ. Можете ли вы переопределить() внутри B? –

+0

Хорошо переписывание - это что-то, чего я хочу избежать, если это возможно. –