Почему `self` в объектах Python является неизменным? - PullRequest
25 голосов
/ 19 июня 2009

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

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

t = Test()
print t

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

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

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

Ответы [ 6 ]

61 голосов
/ 19 июня 2009

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

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

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

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

t = Test()
print t

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

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

10 голосов
/ 19 июня 2009

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

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

class Test(object):
    def __new__(*args):
        return 5
3 голосов
/ 19 июня 2009

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

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

При всем этом я бы настоятельно рекомендовал не менять себя.

1 голос
/ 19 июня 2009

Иногда вы хотите сделать это, но не с неизменяемыми типами, такими как 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]
1 голос
/ 19 июня 2009

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

0 голосов
/ 19 июня 2009
class Test(object):
    def __init__(self):
        self = 5

t = Test()
print t

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

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

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

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