PythonWin的交互式Python shell为何调用构造函数两次?
在回答Python中的静态类变量这个问题时,
我发现PythonWin的PyWin32版本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]
>>>
而Python的解释器却能正确处理这个问题。
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]
>>>
3 个回答
1
还有两个小补充点。
首先,self.__class__.l.append(1)
这个写法其实不太合理。
直接用 self.l.append(1)
就可以了。Python 会先在实例里找这个变量,如果找不到再去类里找。
更重要的是,类级别的变量一般用处不大。类级别的常量有时候可以用,但即使这样也很难说得通。
在 C++ 和 Java 里,类级别的(static
)变量看起来很方便,但其实没什么实质性的价值。教新手的时候也很难,常常会浪费很多时间在细节上,而且不太实用。如果你想知道创建了多少个 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 混在一起。从长远来看,我觉得一个类既是某个东西又是某个东西的集合会让人感到困惑。
简单的比复杂的好。
2
Dave Webb 说得对,你可以通过添加一个打印语句来验证这一点:
>>> class X:
... l = []
... def __init__(self):
... print 'inited'
... self.__class__.l.append(1)
...
然后,当你在 X().
后面输入一个句点时,它会先打印出 inited
,然后再给你显示补全的提示框。
3
我猜测是这样的。PythonWin编辑器提供了自动补全功能,也就是说,当你输入 myobject.
时,它会弹出一个小窗口,显示所有可用的方法名称。所以我认为当你输入 X().
时,它在后台创建了一个 X
的实例,并执行了 dir
或类似的操作来查找这个对象的属性。
因此,构造函数实际上只会为每个对象运行 一次,但为了让你能够互动,它在后台默默地创建对象,而不会告诉你。