Python __init__ проблема с аргументом - PullRequest
3 голосов
/ 31 января 2010

У меня проблемы с пониманием того, что происходит с аргументами инициализации класса, которые являются списками
как:

class A(object):
    def __init__(self, argument=[]):  
        self.argument = argument[:]  

или

def __init__(self,argument=None):  
    self.arguments = arguments or []  

или

def __init__(self, argument=[]):  
    self.argument = argument  

Этого нельзя сделать, потому что значение по умолчанию для каждого объекта A будет указывать на один и тот же фрагмент памяти. Я не могу понять, что здесь происходит и как это происходит.

Ответы [ 3 ]

6 голосов
/ 31 января 2010

Это хорошо известный питон гоча .

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

Обычный способ иметь дело с подобными случаями - это обращаться с ним, как во втором примере:

def __init__(self, arguments=None):  
    self.arguments = arguments or []

Но если вам нужно иметь список со всеми вашими аргументами, вы можете просто использовать аргумент Python для распаковки .

Работает так:

def my_function(*args):
    print args

тогда в вашем методе будет доступ к кортежу со всеми переданными аргументами. Так что, если вы назвали свою функцию так:

>>> my_function(1, 2, 3)

Ваш вывод будет выглядеть так:

(1, 2, 3)

Круто то, что вы всегда можете использовать его противоположным образом, поэтому предположим, что у вас есть список (или кортеж), и вы хотите передать каждый элемент списка в качестве позиционного аргумента своей функции. Вы бы сделали это:

>>> my_list = [1, 2, 3]
>>> my_function(*my_list)

И, что касается вашей функции, она такая же, как и предыдущий вызов.

Вы должны прочитать документацию , на которую я указал , а также раздел, в котором более подробно рассматриваются определения функций .

4 голосов
/ 31 января 2010

Список создается при запуске определения, а не при выполнении метода.

1 голос
/ 31 января 2010

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

Вкратце, вот как это работает: в Python ничего не сохраняется как имя по значению. Все хранится внутри как указатель на объект Python. Когда вы делаете:

a = [1,2,3]
b = a

Вы не устанавливаете b в значение из a. Вы устанавливаете b для ссылки на тот же объект. Итак утверждение:

a is b

Верно, так как имена ссылаются на один и тот же объект.

a = [1,2,3]
b = [1,2,3]
a is b

Это вернет false. Причина в том, что теперь вы создали два разных объекта. Итак, строка:

self.argument = argument[:]

- это (необходимый) способ создания копии self.argument, чтобы он не ссылался на один и тот же объект.

...