Почему новые экземпляры класса делятся членами с другими экземплярами? - PullRequest
2 голосов
/ 21 ноября 2008
class Ball:
  a = []
  def __init__(self):
    pass

  def add(self,thing):
    self.a.append(thing)

  def size(self):
    print len(self.a)

for i in range(3):
  foo = Ball()
  foo.add(1)
  foo.add(2)
  foo.size()

Я ожидаю возврата:

2
2
2

Но я получаю:

2
4
6

Почему это? Я обнаружил, что, выполнив a = [] в init , я могу обойти это поведение, но я не совсем понимаю, почему.

Ответы [ 3 ]

4 голосов
/ 21 ноября 2008

DOH

Я только что понял, почему.

В приведенном выше случае a является атрибутом класса, а не атрибутом данных - они являются общими для всех Balls (). Комментирование a = [] и помещение его в блок init означает, что вместо этого это атрибут данных. (И я не мог получить к нему доступ тогда с помощью foo.a, что я не должен был делать в любом случае.) Кажется, что атрибуты класса действуют как статические атрибуты класса, они используются всеми экземплярами.

Вау.

Хотя один вопрос: CodeCompletion отстой вот так. В классе foo я не могу сделать self. (Переменная), потому что он не определяется автоматически - он определяется функцией. Могу ли я определить переменную класса и заменить ее переменной данных?

2 голосов
/ 21 ноября 2008

Что вы, вероятно, хотите сделать, это:

class Ball:
  def __init__(self):
    self.a = []

Если вы используете просто a = [], он создает локальную переменную в функции __init__, которая исчезает при возврате функции. Присвоение self.a делает его переменной экземпляра, к которой вы стремитесь.

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

1 голос
/ 21 ноября 2008

«Могу ли я определить переменную класса и заменить ее переменной данных?»

Нет. Это разные вещи. Переменная класса существует ровно один раз - в классе.

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

Лучше попробовать другую IDE. Komodo Edit * Кодовые дополнения кажутся разумными.

Если у вас так много переменных с такими длинными именами, что завершение кода действительно полезно, возможно, вам следует уменьшить классы или использовать более короткие имена. Шутки в сторону.

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

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