Подтвердить что ты не робот

Почему `self` в объектах Python неизменен?

Почему я не могу выполнить действие, подобное следующему:

class Test(object):
    def __init__(self):
        self = 5

t = Test()
print t

Я ожидаю, что он напечатает 5, поскольку мы перезаписываем экземпляр с ним, но вместо этого он ничего не делает. Даже не выдает ошибку. Просто игнорирует назначение.

Я понимаю, что вряд ли найдутся ситуации, когда вы захотите это сделать, но по-прежнему кажется странным, что вы не можете.

Обновление: Теперь я понимаю, почему это не работает, но мне все равно хотелось бы узнать, есть ли способ заменить экземпляр из экземпляра.

4b9b3361

Ответ 1

Любое простое назначение любому аргументу любой функции ведет себя точно так же в Python: связывает это имя с другим значением и ничего не делает. "Никакой особый случай не является достаточно сложным, чтобы нарушать правила", как говорит Дзен Питона! -)

Итак, далека от того, что это нечетно (что просто = назначение определенного аргумента в конкретной функции не имеет никакого внешнего эффекта вообще), было бы совершенно удивительно, если бы этот конкретный случай работал каким-либо другим способом только из-за имена рассматриваемой функции и аргумента.

Если вы когда-либо захотите создать класс, который создает объект другого типа, чем сам, такое поведение, конечно, вполне возможно, но оно получается путем переопределения специального метода __new__, не __init__:

class Test(object):
    def __new__(cls):
        return 5

t = Test()
print t

Это испускает 5. Поведение __new__/__init__ в Python является примером шаблона проектирования "двухступенчатая конструкция": собственно "конструктор" __new__ (он строит и возвращает объект (обычно неинициализированный) (обычно новый рассматриваемого типа/класса); __init__ - это "инициализатор", который правильно инициализирует новый объект.

Это позволяет, например, построить объекты, которые неизменяемы после построения: в этом случае все должно быть сделано в __new__, прежде чем объект неизменяемого объекта будет построен, поскольку, учитывая, что объект является неизменным, __init__ не может мутировать его, чтобы инициализировать его.

Ответ 2

Он не игнорирует задание. Назначение работает очень хорошо, вы создали локальное имя, которое указывает на данные 5.

Если вы действительно хотите делать то, что вы делаете...

class Test(object):
    def __new__(*args):
        return 5

Ответ 3

Я только что проверил быстрый тест, и вы можете назначить себя. Внутри метода init() напечатайте значение self. Вы увидите, что это 5.

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

Все, что было сказано, я настоятельно советовал бы никогда не изменять меня.

Ответ 4

р. Эгон Шпенглер: Было бы плохо.
Д-р Питер Венкман: ​​Я расплывчатый на все хорошо/плохо. Что значит "плохо"? Д-р Эгон Шпенглер: Попробуйте представить всю жизнь, как вы знаете, что она мгновенно останавливается, и каждая молекула в вашем теле взрывается со скоростью света.

Ответ 5

Иногда вы хотите сделать это, хотя не с неизменяемыми типами, например int:

>>> class Test(list):
    ... def __init__(self):
    ...    list.__init__(self, [1,2,3])   # self = [1,2,3] seems right, but isn't

>> t = Test()
>> print t
[1, 2, 3]

Ответ 6

class Test(object):
    def __init__(self):
        self = 5

t = Test()
print t

похож на этот PHP (только другой язык, который я знаю, извините)

class Test {
    function __construct() {
            $this = 5;
        }
}

Я не понимаю, как это имеет смысл. заменив экземпляр значением?