为啥 Python 新式类中的 __new__ 不是类方法?
Posted
技术标签:
【中文标题】为啥 Python 新式类中的 __new__ 不是类方法?【英文标题】:Why isn't __new__ in Python new-style classes a class method?为什么 Python 新式类中的 __new__ 不是类方法? 【发布时间】:2012-02-23 21:52:55 【问题描述】:Python 2.2 的变更日志(其中引入了新式类)对 __new__
函数有以下说明:
__new__
是静态方法,不是类方法。我最初认为它必须是一个类方法,这就是我添加classmethod
原语的原因。不幸的是,对于类方法,向上调用在这种情况下无法正常工作,因此我不得不将其设为静态方法,并以显式类作为其第一个参数。
但是,我想不出为什么类方法不能用于此目的,而且它肯定会更好看。为什么__new__
最终没有成为类方法?当 Guido 说“在这种情况下向上调用不起作用”时,他指的是什么?
【问题讨论】:
【参考方案1】:__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()
。 You need a place to pass cls
explicitly in this case:
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())
【讨论】:
@Duncan:我故意使用new
而不是__new__
。如果不清楚,请发表评论,我会尽力详细说明。
我认为,如果您使用的名称比去掉下划线更清晰一点,它会更清楚,但我现在明白了,谢谢。
不过,这实际上何时会成为问题?如果你想要subcls
的实例,为什么不调用subcls.new()
?按照您描述的方式进行操作只会导致无法在 subcls
上运行正确的 __new__
函数。
@Dolda2000:更常见的情况是调用父级__new__
而不使用super()
。 You need a place to pass cls
explicitly in this case.
@Searcherer:没有。 new()
和 __new__
是完全不同的方法。这里的“new”是一个普通的类方法(它可以是任何名称,例如,“new_method_to_illustrate_some_point_in_the_answer”__new__ 是魔术(静态)方法——它必须被称为 __new__
。以上是关于为啥 Python 新式类中的 __new__ 不是类方法?的主要内容,如果未能解决你的问题,请参考以下文章
python单例模式控制成只初始化一次,常规型的python单例模式在新式类和经典类中的区别。