为啥 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单例模式在新式类和经典类中的区别。

python中的__new__与__init__,新式类和经典类(2.x)

Python中的__new__()方法的使用

Python中的__new__()方法的使用

Python 的 __new__()方法与实例化

Python新式类 单例模式与作用域