Почему `self` в объектах Python неизменен?
Почему я не могу выполнить действие, подобное следующему:
class Test(object):
def __init__(self):
self = 5
t = Test()
print t
Я ожидаю, что он напечатает 5
, поскольку мы перезаписываем экземпляр с ним, но вместо этого он ничего не делает. Даже не выдает ошибку. Просто игнорирует назначение.
Я понимаю, что вряд ли найдутся ситуации, когда вы захотите это сделать, но по-прежнему кажется странным, что вы не можете.
Обновление: Теперь я понимаю, почему это не работает, но мне все равно хотелось бы узнать, есть ли способ заменить экземпляр из экземпляра.
Ответы
Ответ 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;
}
}
Я не понимаю, как это имеет смысл. заменив экземпляр значением?