Как инициализировать новый экземпляр *как* существующий экземпляр?

Иногда в __init__ у меня уже есть экземпляр, которым должен стать self, и я просто хочу установить его на это.
Простейший случай состоит в том, что аргумент, используемый для инициализации Foo, сам является Foo.
(Foo(Foo(x)) == Foo(x) точно так же, как set({1, 2}) == {1, 2}.)
В примере это case_trivial. Но есть еще case_variadic.

В настоящее время я должен установить каждый атрибут самостоятельно. Есть ли способ сделать это в одну строку?

from variadic_foo_operations import foo_addition, foo_multiplication


class Foo(object):

    def __init__(self, arg=None, addends=None, factors=None):

        case_arg = arg is not None
        case_normal = case_arg and type(arg) == int
        case_trivial = case_arg and type(arg) == Foo

        case_add = addends is not None
        case_multiply = factors is not None
        case_variadic = case_add or case_multiply

        if case_normal:
            self.bar = arg
            self.double_bar = 2 * arg
        elif case_trivial:
            the_foo_i_want = arg
        elif case_variadic:
            operation = foo_addition if case_add else foo_multiplication
            operands = addends if case_add else factors
            current_foo = Foo(0) if case_add else Foo(1)  # neutral element
            for operand_foo in operands:
                current_foo = operation(current_foo, operand_foo)
            the_foo_i_want = current_foo

        if case_trivial or case_variadic:
            # What I would like:
            self = the_foo_i_want
            # What I have to do instead:
            self.bar = the_foo_i_want.bar
            self.double_bar = the_foo_i_want.double_bar

person Watchduck    schedule 19.07.2020    source источник
comment
Нет, к тому времени, когда __init__ вызывается, Python уже создал новый экземпляр - self в этот момент является просто параметром метода, назначение которого не имеет никакого влияния вне метода. Может быть, вы хотите вместо этого переопределить __new__?   -  person jonrsharpe    schedule 19.07.2020
comment
Похоже, вам нужен конструктор копирования, но Python не предоставляет ничего подобного из коробки. В качестве примечания, я думаю, что этот метод делает слишком много разрозненной работы. Я бы предложил оставить в вашем __init__ только инициализацию и ввести вспомогательные функции, реализующие расчет. Таким образом, у вас будет что-то вроде def new_foo_add(addends): ...; return Foo(bar=..., ...). Кроме того, type(arg) == Foo сломается, если вы когда-нибудь наследуете от Foo.   -  person Norrius    schedule 19.07.2020
comment
@Norrius Если addends — это один из способов инициализации Foo, то __init__ — это то место, где он у меня есть. Как бы вы довели его до этой вспомогательной функции?   -  person Watchduck    schedule 19.07.2020


Ответы (1)


Нашел ответ здесь: Как скопировать все свойства объекта в другой объект

self.__dict__ = the_foo_i_want.__dict__.copy()
person Watchduck    schedule 19.07.2020