This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author serhiy.storchaka
Recipients jaraco, serhiy.storchaka
Date 2021-03-06.15:24:04
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1615044244.58.0.163016843485.issue43413@roundup.psfhosted.org>
In-reply-to
Content
> Hmm, but in my experience, tuple on Python 3.6 doesn't take keyword arguments either:

They do.

>>> tuple(sequence='abc')
('a', 'b', 'c')

>>> list(sequence='abc')
['a', 'b', 'c']
>>> int(x='123')
123
>>> bool(x='123')
True
>>> float(x='123')
123.0

It was changed in bpo-29695.

But accepting arbitrary keyword arguments is another issue.

Object creation in Python can be customized be implementing special methods __new__ and __init__. They both are called sequentially with arguments passed to the constructor. If object is mutable, it is enough to implement __init__. If the object contains immutable data which should be initialized at creation time, it needs __new__, and __init__ is not necessary. So the list class has __init__, but the tuple and int classes have __new__. Usually class implements only one of __new__ or __init__, and inherits the other one from parent classes.

Since positional and keyword arguments are passed to both __new__ and __init__, they should accept same arguments. If __new__ and __init__ are inherited from parent class, they cannot know about arguments supported in the other method. Therefore object's __new__ and __init__ accept and ignore all arguments (if the other method is overridden).

Implementations of __new__ for most builtin classes which accept only positional arguments accept and ignore also arbitrary keyword arguments in subclasses. It makes easier to implement a subclass with non-trivial __init__. You just add additional keyword arguments which will be ignored in __new__. It is long tradition. Example:

    if (type == &cycle_type && !_PyArg_NoKeywords("cycle()", kwds))
        return NULL;

bpo-20186 just used this idiom for tuple and several other classes. It is a feature which makes subclassing these classes easier. And with converting more classes to Argument Clinic it is now used in more and more classes.

Now, perhaps it would be more correct to test `type->tp_init == cycle_type.tp_init` or `type->tp_init != PyBaseObject_Type.tp_init` instead of `type == &cycle_type`. It will ignore keyword arguments only if __init__ is overridden. If __init__ is overridden, it is now responsible for validating arguments.
History
Date User Action Args
2021-03-06 15:24:04serhiy.storchakasetrecipients: + serhiy.storchaka, jaraco
2021-03-06 15:24:04serhiy.storchakasetmessageid: <1615044244.58.0.163016843485.issue43413@roundup.psfhosted.org>
2021-03-06 15:24:04serhiy.storchakalinkissue43413 messages
2021-03-06 15:24:04serhiy.storchakacreate