Безопасно ли заменить собственный объект другим объектом того же типа в методе? - PullRequest
29 голосов
/ 01 августа 2009

Я хотел бы заменить экземпляр объекта другим экземпляром внутри метода, подобного этому:

class A:
    def method1(self):
        self = func(self)

Объект извлекается из базы данных.

Ответы [ 7 ]

53 голосов
/ 01 августа 2009

Маловероятно, что замена переменной 'self' приведет к тому, что вы пытаетесь сделать, чего нельзя добиться, просто сохранив результат функции func (self) в другой переменной. «self» - это локальная переменная, определенная только на время вызова метода, которая используется для передачи экземпляра класса, с которым ведется работа. Замена self на самом деле не заменит ссылки на исходный экземпляр класса, содержащиеся в других объектах, и не создаст долговременную ссылку на новый экземпляр, который был ему присвоен.

15 голосов
/ 06 июня 2016

Насколько я понимаю, если вы пытаетесь заменить текущий объект другим объектом того же типа (при условии, что func не изменит тип объекта) из функции-члена. Я думаю, что это достигнет этого

class A:
    def method1(self):
        newObj = func(self)
        self.__dict__.update(newObj.__dict__)
10 голосов
/ 30 августа 2013

Это не прямой ответ на вопрос, но в постах ниже есть решение для того, что amirouche пытался сделать:

А вот пример рабочего кода (Python 3.2.5).

class Men:
    def __init__(self, name):
        self.name = name

    def who_are_you(self):
        print("I'm a men! My name is " + self.name)

    def cast_to(self, sex, name):
        self.__class__ = sex
        self.name = name

    def method_unique_to_men(self):
        print('I made The Matrix')


class Women:
    def __init__(self, name):
        self.name = name

    def who_are_you(self):
        print("I'm a women! My name is " + self.name)

    def method_unique_to_women(self):
        print('I made Cloud Atlas')


men = Men('Larry')
men.who_are_you()
#>>> I'm a men! My name is Larry
men.method_unique_to_men()
#>>> I made The Matrix


men.cast_to(Women, 'Lana')
men.who_are_you()
#>>> I'm a women! My name is Lana
men.method_unique_to_women()
#>>> I made Cloud Atlas

Обратите внимание на self.__class__, а не self.__class__.__name__. То есть эта техника не только заменяет имя класса, но и фактически преобразует экземпляр класса (по крайней мере, оба они имеют одинаковые id()). Кроме того, 1) я не знаю, является ли «безопасным заменить собственный объект другим объектом того же типа в методе [собственный объект]»; 2) работает с различными типами объектов, а не только с объектами одного типа; 3) он работает не совсем так, как хотел amirouche: вы не можете инициализировать класс как Class(args), только Class() (я не профессионал и не могу ответить, почему это так).

6 голосов
/ 01 августа 2009

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

Обратите внимание, что вы меняете только переменную, как и любую другую. Выполнение self = 123 - это то же самое, что и abc = 123. self является только ссылкой на текущий экземпляр в методе. Вы не можете изменить свой экземпляр, установив self.

Что должен сделать func(self), это изменить переменные вашего экземпляра:

def func(obj):
    obj.var_a = 123
    obj.var_b = 'abc'

Тогда сделайте это:

class A:
    def method1(self):
        func(self) # No need to assign self here
0 голосов
/ 31 мая 2019

Во многих случаях хороший способ добиться того, чего вы хотите, - это позвонить снова __init__. Например:

class MyList(list):
    def trim(self,n):
        self.__init__(self[:-n])

x = MyList([1,2,3,4])
x.trim(2)
assert type(x) == MyList
assert x == [1,2]

Обратите внимание, что это идет с несколькими допущениями, такими как все, что вы хотите изменить в отношении объекта, установленного в __init__. Также помните, что это может вызвать проблемы с наследованием классов, которые переопределяют __init__ несовместимым образом.

0 голосов
/ 25 января 2018

Да, в этом нет ничего плохого. Ненавистники пусть ненавидят. (Смотрит на тебя Пичарм с твоим in most cases imaginable, there's no point in such reassignment and it indicates an error).

Ситуация, когда вы могли бы сделать это:

some_method(self, ...):

    ...

    if(some_condition):
        self = self.some_other_method()

    ...

    return ...

Конечно, вы можете запустить тело метода, переназначив self на другую переменную, но если вы обычно не делаете это с другими параметрами, зачем делать это с self?

0 голосов
/ 26 сентября 2013

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

Конечно, можно присвоить его новому объекту, но затем использование нового объекта будет переливаться через остальную часть кода в методе. Переназначение его на себя оставляет остальную часть метода нетронутой.

class aclass:

    def methodA(self):
        ...
        if condition:
            self = replace_by_derived(self)
            # self is now referencing to an instance of a derived class
            # with probably the same values for its data attributes

        # all code here remains untouched
        ...
        self.methodB() # calls the methodB of derivedclass is condition is True
        ...

    def methodB(self):
        # methodB of class aclass
        ...

class derivedclass(aclass):
    def methodB(self):
        #methodB of class derivedclass
        ...

Но кроме такого особого случая использования, я не вижу никаких преимуществ, чтобы заменить себя.

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