为什么 Python 新式类中的 __new__ 不是类方法?

发布于 2025-01-01 10:56:25 字数 355 浏览 0 评论 0原文

Python 2.2 的变更日志(引入了新样式类)对 __new__ 函数进行了以下说明:

__new__ 是静态方法,而不是类方法。我最初认为它必须是一个类方法,这就是我添加 classmethod 原语的原因。不幸的是,对于类方法,向上调用在这种情况下无法正常工作,因此我必须将其设为静态方法,并将显式类作为其第一个参数。

但是,我想不出为什么类方法不能用于此目的,而且它肯定看起来会更好。为什么__new__最终没有成为类方法?当 Guido 说“在这种情况下向上调用不起作用”时,他指的是什么?

The Changelog for Python 2.2 (where new-style classes were introduced) says the following about the __new__ function:

__new__ is a static method, not a class method. I initially thought it would have to be a class method, and that's why I added the classmethod primitive. Unfortunately, with class methods, upcalls don't work right in this case, so I had to make it a static method with an explicit class as its first argument.

However, I cannot think of why class methods wouldn't work for this purpose, and it would certainly look better. Why didn't __new__ end up as a class method in the end? What does Guido refer to when he says that "upcalls don't work right in this case"?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花间憩 2025-01-08 10:56:25

__new__ 是静态方法,当您在其中创建子类的实例时,允许使用用例:

return super(<currentclass>, cls).__new__(subcls, *args, **kwargs)

的写法为:

return super(<currentclass>, cls).new(*args, **kwargs)

如果 new 是一个类方法,则上面 没有地方放置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())

__new__ being static method allows a use-case when you create an instance of a subclass in it:

return super(<currentclass>, cls).__new__(subcls, *args, **kwargs)

If new is a class method then the above is written as:

return super(<currentclass>, cls).new(*args, **kwargs)

and there is no place to put subcls.

I don't really see when that would be a proper use of __new__, though. Maybe I'm not seeing it, but that just seems to me to be a completely pathological use of it (and it should be said, that if you still really want it, then you could access it with object.__new__.__func__). At the very least, I find it very hard to imagine that it would have been the reason for Guido to change __new__ from being a class method to a static method.

A more common case would be to call parent __new__ without using 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())
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文