Serhiy Storchaka <storchaka+cpyt...@gmail.com> added the comment:

> 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.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue43413>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to