0

I noticed that a definition of __new__ begins as follows:

def __new__(cls, *args, **kw):
    # This is needed because object.__new__ only accepts
    # the cls argument.
    new_meth = super().__new__
    if new_meth is object.__new__:
        inst = new_meth(cls)
    else:
        inst = new_meth(cls, **kw)

Is this standard? Testing for method identity seems weird. Why doesn't object.__new__ just ignore arguments other than the cls? What method is normally run when __new__ is called on a class — if it's object.__new__ then does the bytecode generator just not push the arguments onto the stack?

Neil G
  • 32,138
  • 39
  • 156
  • 257
  • possible explanation at: http://stackoverflow.com/a/19277824/2904896 – metatoaster Sep 24 '15 at 03:48
  • @metatoaster: Thank you. That explains a lot. I still don't understand why I should have to write the above code. Why doesn't it ignore arguments in the case where both `new` and `init` are defined? – Neil G Sep 24 '15 at 03:54
  • @brenbarn: Please don't close questions like this before verifying that everything in my question is a duplicate. I'm asking about a case that is not covered by the other question. – Neil G Sep 24 '15 at 03:55
  • @NeilG: Which part of your question is answered neither by the marked duplicate nor by the question it links to? – BrenBarn Sep 24 '15 at 03:59
  • If you opened the further links in the answer you would have found this as to why `__new__` has been changed to not take arg/kwargs: http://bugs.python.org/issue1683368 – metatoaster Sep 24 '15 at 04:00
  • @metatoaster: That still doesn't explain why `__new__` doesn't ignore arguments that `__init__` will ultimately process. – Neil G Sep 24 '15 at 04:02
  • @brenbarn The fourth case when both new and init are both overridden. In that case, it doesn't seem to make sense for `__new__` to complain about extra arguments since these might be handled by `__init__`. If you look at the linked bug, and follow Raymond's pattern for init on new as well, you will get errors. Also I asked about the bytecodes generated, which I'd still like to know. – Neil G Sep 24 '15 at 04:03
  • You can never override `object.__new__` which takes no arguments **ever** (this is thoroughly explained in that issue linked), which `super().__new__` will reference if it's called within a class that directly inherits from `object`. – metatoaster Sep 24 '15 at 04:12
  • @metatoaster: Of course you can override `__new__`. Override doesn't mean replace. You're still supposed to call super. – Neil G Sep 24 '15 at 04:13
  • @BrenBarn: Hello? Can you reopen this question please. Thanks. – Neil G Sep 24 '15 at 04:14
  • As in, you can never override `object.__new__` itself especially if you literally just call this via `super().__new__`, because you are calling `object.__new__` through this indirection via `super`. Read http://bugs.python.org/msg219300 – metatoaster Sep 24 '15 at 04:15
  • @metatoaster: I think you are not using the standard definition of "override". Override means define a method on a class that is called instead of the parent class' method. The overriding (child class) method can still call the overridden (parent class) method. – Neil G Sep 24 '15 at 04:17
  • I.e. if I am not being clear enough: `super()` falls through to `object` class under certain cases, and since you can't call `object.__new__` with arguments and something you can't replace/override/whatever you have to play ball with it or have your code unexpectedly die in a fire. – metatoaster Sep 24 '15 at 04:18
  • @metatoaster: you are supposed to call super until it reaches object for both new and init overrides. There is no argument about that. The question is why object doesn't ignore arguments to new when init is also overridden. It already ignores arguments when init is overridden but new is not. – Neil G Sep 24 '15 at 04:20
  • 1
    And we are back to where we started: it's a design decision, explained in the question/answer, and even more thoroughly explained in the issue I linked again here. – metatoaster Sep 24 '15 at 04:21
  • @metatoaster: that question discusses three cases: neither overridden, or one overridden, or the other. I am asking about when both are overridden. – Neil G Sep 24 '15 at 04:21
  • @NeilG: If your question is specifically about the case where both are overridden, you should edit it to ask that, and remove the parts that re-ask what's already answered in the duplicate (which, right now, is all of it, as far as I can see). Your question doesn't say anything about overriding or `__init__` or any relationship between them. – BrenBarn Sep 24 '15 at 05:28

0 Answers0