2008-09-17 3 views
2

Отвечая Static class variables in PythonPythonWin в python интерактивные оболочки, вызывающие конструкторы дважды?

Я заметил, что интерпретатор PythonWin PyWin32 build 209.2, кажется, оценивает дважды?

PythonWin 2.5 (r25:51908, Mar 9 2007, 17:40:28) [MSC v.1310 32 bit (Intel)] on win32. 
Portions Copyright 1994-2006 Mark Hammond - see 'Help/About PythonWin' for further copyright information. 
>>> class X: 
...  l = [] 
...  def __init__(self): 
...   self.__class__.l.append(1) 
...   
>>> X().l 
[1, 1] 
>>> 

в то время как интерпретатор питона делает правильно

C:\>python 
ActivePython 2.5.0.0 (ActiveState Software Inc.) based on 
Python 2.5 (r25:51908, Mar 9 2007, 17:40:28) [MSC v.1310 32 bit (Intel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> class X: 
... l = [] 
... def __init__(self): 
...  self.__class__.l.append(1) 
... 
>>> X().l 
[1] 
>>> 
+0

@Gregory, это больше похоже на отчет об ошибке для PyWin, чем вопрос SO. – 2008-09-17 08:58:24

ответ

3

Мое предположение состоит в следующем. Редактор PythonWin предлагает автозаполнение для объекта, т. Е. При вводе myobject. он предлагает небольшое всплывающее окно всех доступных имен методов. Поэтому я думаю, что когда вы вводите X()., он создает экземпляр X в фоновом режиме и делает dir или аналогично, чтобы узнать атрибуты объекта.

Таким образом, конструктор запускается только один раз для каждого объекта, но для интерактивности он создает объекты в фоновом режиме, не сообщая вам об этом.

1

Две небольшие дополнительные точки.

Во-первых, self.__class__.l.append(1) на самом деле неразумно.

Просто скажите self.l.append(1). Python ищет экземпляр перед его поиском в классе для ссылки.

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

В C++ и Java переменные класса ('static') кажутся удобными, но не имеют большого значения. Их трудно научить n00bz - часто тратя много времени в классе на minutia - и они не очень практичны. Если вы хотите знать все экземпляры X, которые были созданы, вероятно, лучше создать класс XFactory, который не полагается на переменные класса.

class XFactory(object): 
    def __init__(self): 
     self.listOfX= [] 
    def makeX(self, *args, **kw): 
     newX= X(*args,**kw) 
     self.listOfX.append(newX) 
     return newX 

Отсутствие аномалий переменной уровня. И он не объединяет X с коллекцией X. В конечном счете, я нахожу это сбивающим с толку, когда класс - это как нечто, так и некоторые вещи.

Упрощенный вариант лучше, чем комплекс.

+0

Если вы посмотрите на мое сообщение, я ответил на статический вопрос. Поэтому я хочу специально изменить переменную класса, а не переменную экземпляра. Код, который я написал, является «самым чистым» способом явного доступа к переменным класса. – Gregory 2008-09-17 22:38:53

2

Дэйв Уэбб является правильным, и вы можете увидеть это, добавив оператор печати:

>>> class X: 
...  l = [] 
...  def __init__(self): 
...    print 'inited' 
...    self.__class__.l.append(1) 
...    

Затем, как только вы наберете период в X(). печатает inited до предлагать вам завершающие всплывающее окно.