2017-02-10 4 views
1

В настоящее время у меня есть @classmethod, который возвращает правильный класс с заданной переменной. Это выглядит примерно так:Имейте класс для инициализации объекта из другого класса

class Parent(): 
    @classmethod 
    def GetInstance(cls, variable): 
    if variable == 'foo': 
     return Child() 


class Child(Parent): 
    def Something(self): 
    pass 

instance = Parent.GetInstance('foo') 
result = instance.Something() 

Я предпочитаю не определить и использовать GetInstance. Вместо этого, я хотел бы, чтобы Main() просто:

instance = Parent('foo') 
result = instance.Something() 

Сохраняя все преимущества структуры выше. Я хочу, чтобы класс Parent() возвращал объект класса Child() при вызове без использования метода. __init__, к сожалению, не помогает, поскольку он ничего не может вернуть. Есть идеи?

+0

Вы можете использовать '__new__', но во многих случаях вам лучше просто написать заводскую функцию. – BrenBarn

+0

Да, модель класса Python не просто поддерживает это. Я не могу придумать способ, потому что, как вы выяснили, '__init__' не любит« возвращать »вещи. Просто используйте фабричный шаблон ... это хорошо известно. –

+0

@BrenBarn Да, я полагаю, вы могли бы использовать '__new__'. Это было бы полностью переработанное решение проблемы без проблем. Это было бы совершенно неожиданно для любого, кто использует ваш «класс». –

ответ

-1

Добавить список детей [] в вашем родительском классе:

class Parent(): 
    def __init__(self): 
     children = list() 

Таким образом, вы можете создать дочерний объект(), а затем добавить его, выполнив:

child - Child() # create new child obj 
parent.children.append(child) 

Затем он должен быть простым, чтобы получить ребенка из списка детей, которые вы хотите использовать в петле и т. д.

+0

Целью является не создание списка дочерних элементов, а передача параметра, а в случае параметра '' foo'', вместо этого построить дочерние элементы. –

+0

@WillemVanOnsem Почему бы вам просто не опубликовать ответ? – codeglove26

+0

Я сделал, пока не понял, что ответ не был таким тривиальным. Когда у вас есть права администратора, вы даже можете увидеть этот ответ;). –

0

Просто переопределить 'новый' специальный метод. Это метод «new», который отвечает за вызов создания экземпляра, выделение памяти, а затем его инициализацию путем вызова «init». Конкретно

новый является статическим методом класса, в то время как инициализация является методом экземпляра. новый должен создать экземпляр первым, поэтому init может его инициализировать. Обратите внимание, что init принимает параметр self как параметр. Пока вы не создаете экземпляр, нет я.

+0

Похоже, что проблема в том, что вы получите обратный вызов: '__new__' вызывает 'Child()', child вызывает 'Child' '__new__', который будет вызывать' Parent '' __new__', и вы получите звонок дважды. –

0

EDIT Хорошо, я вернулся и исправил это. Полностью хриплый и очень хрупкий. Надеюсь, вы не захотите продолжать это. Я помещаю это здесь как иллюстрацию , почему это плохая идея.

Вот эскиз того, как вы может выполнить это. Но, пожалуйста, просто используйте заводской метод.

>>> class Parent(object): 
...  def __new__(typ, *args, **kwargs): 
...   if args and args[0] == 'foo': 
...    return Child() 
...   else: 
...    return super(Parent, typ).__new__(typ) 
... 
>>> class Child(Parent): 
...  __new__ = object.__new__ 
... 
>>> a = Parent('foo') 
>>> a 
<__main__.Child object at 0x1023275f8> 
>>> p = Parent() 
>>> p 
<__main__.Parent object at 0x1023275c0> 
>>> 
+0

Они хотят иметь «ребенка» в качестве ребенка «Родительского», откуда я беру на себя трудности с «__new__». –

+0

@KevinMGranger дерьмо, моя ошибка. Да, это становится беспорядочно быстрым. Gimme a sec ... –

+0

@KevinMGranger Хорошо, теперь у меня рабочий скелет, хрупкий, как и все ад. –

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