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

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

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

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

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

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

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

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

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

 class Test(object): def __new__(cls): return 5 t = Test() print t 

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

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

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

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

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

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

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

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

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

Иногда вы хотите сделать это, хотя не с неизменяемыми типами, такими как 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] 
 class Test(object): def __init__(self): self = 5 t = Test() print t 

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

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

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