2010-01-08 1 views
0

на основе this answer, о том, как __new__ и __init__ должны работать в Python,Python множественное наследование: что делает это динамически?

Я написал этот код, чтобы динамически определить и создать новый класс и объект.

class A(object): 
    def __new__(cls): 
     class C(cls, B): 
      pass 
     self = C() 
     return self 

    def foo(self): 
     print 'foo' 

class B(object): 
    def bar(self): 
     print 'bar' 

a = A() 
a.foo() 
a.bar() 

В основном, потому что __new__ А возвращает динамически созданный C, который наследует А и В, он должен иметь атрибут bar.

Почему Cне имеет атрибут bar?

+0

Что вопрос? – 2010-01-08 09:33:32

+0

На основании какого ответа? Вам не хватает ссылки? –

+0

Roger, Dominic, Yup link отсутствует. Теперь обновите вопрос, соответственно. –

ответ

7

Resolve бесконечная рекурсия:

class A(object): 
    def __new__(cls): 
    class C(cls, B): 
     pass 
    self = object.__new__(C) 
    return self 

(Благодаря balpha за указание на актуальный вопрос.)

3

Если ваш вопрос «Как я могу сделать это» – это работает:

class A(object): 
    @classmethod 
    def get_with_B(cls): 
     class C(B, cls): 
     pass 

     return C() 

    def foo(self): 
     print 'foo' 

class B(object): 
    def bar(self): 
     print 'bar' 

a = A.get_with_B() 
a.foo() 
a.bar() 

Если ваш вопрос «Почему не это работает» – это потому, что вы столкнетесь с бесконечной рекурсии при вызове C(), что приводит к A.__new__ вызывается, который снова вызывает C() и т.д.

7

Поскольку нет никакого фактического вопроса в вопросе, я собираюсь т ake это буквально:

Неправильно ли это делать динамически?
Ну, это практически непроницаемо, чрезвычайно непрозрачно и неочевидно для пользователя вашего кода (который включает вас через месяц: P).

Из моего опыта (довольно ограниченно, я должен признать, к сожалению, у меня нет 20 лет программирования под ремнем), потребность в таких решениях указывает на то, что структура класса не определена четко, означает, что есть почти всегда лучший, более читаемый и менее загадочный способ делать такие вещи.

Например, если вы действительно хотите определить базовые классы на лету, вам лучше использовать заводскую функцию, которая вернет соответствующие классы в соответствии с вашими потребностями.

Другой вопрос:
Неправильно ли это делать динамически?
В вашей текущей реализации это дает мне ошибку «Максимальная ошибка рекурсии превышена». Это происходит, потому что A.__new__ называет себя изнутри себя бесконечно (поскольку он наследует от себя и от B).

10: Внутри A.__new__, "cls" установлен на <class '.A'>. Внутри конструктора вы определяете класс C, который наследует от cls (который фактически A) и другого класса B. После экземпляра C вызывается его __new__. Поскольку он не определяет свой собственный __new__, его базовый класс «__new__» вызывается. Базовый класс просто A.
20: GOTO 10