为什么Python新风格类中的__new__不是类方法?
Python 2.2的更新日志提到,__new__
这个函数是一个静态方法,而不是类方法。最开始我以为它应该是个类方法,所以我加上了classmethod
这个东西。但不幸的是,在这种情况下,类方法的调用方式不太对劲,所以我不得不把它做成一个静态方法,并且把类作为第一个参数。
不过,我想不出为什么类方法在这里不适用,而且用类方法看起来肯定更好。那么,为什么最后
__new__
没有成为一个类方法呢?当Guido说“在这种情况下,上层调用不太对劲”时,他指的是什么呢?
1 个回答
31
__new__
是一个静态方法,这样做的好处是你可以在里面创建子类的实例:
return super(<currentclass>, cls).__new__(subcls, *args, **kwargs)
如果 new
是一个类方法,那么上面的代码就会写成:
return super(<currentclass>, cls).new(*args, **kwargs)
但这样就没有地方可以放 subcls
了。
不过,我其实不太明白什么时候使用
__new__
是合适的。也许我没看明白,但我觉得这似乎是个不太正常的用法(而且要说的是,如果你真的想这么做,可以通过object.__new__.__func__
来访问)。至少,我很难想象这会是 Guido 改变__new__
从类方法变成静态方法的原因。
更常见的情况是调用父类的 __new__
,而不使用 super()
。在这种情况下,你需要一个地方来明确传递 cls
:
class Base(object):
@classmethod
def new(cls):
print("Base.new(%r)" % (cls,))
return cls()
class UseSuper(Base):
@classmethod
def new(cls):
print("UseSuper.new(%r)" % (cls,))
return super(UseSuper, cls).new() # passes cls as the first arg
class NoSuper(Base):
@classmethod
def new(cls):
print("NoSuper.new(%r)" % (cls,))
return Base.new() # passes Base as the first arg
class UseFunc(Base):
@classmethod
def new(cls):
print("UseFunc.new(%r)" % (cls,))
return Base.new.im_func(cls) # or `.__func__(cls)`. # passes cls as the first arg
print(UseSuper.new())
print('-'*60)
print(NoSuper.new())
print('-'*60)
print(UseFunc.new())