Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does subclassing change the __init__ signature?

Tags:

python

>>> map(int, ["1", "2"], kw=True)
TypeError: map() takes no keyword arguments

But when subclassing

>>> class Map(map):
...     pass
...
>>> Map(int, ["1", "2"], whydoesthiswork=True)
<__main__.Map at 0x10fe48700>

Why does this now accept keyword argument? Shouldn't it just inherit the __init__from parent?

like image 232
no step on snek Avatar asked Feb 17 '21 18:02

no step on snek


Video Answer


1 Answers

I don't know why, but map.__new__ specifically only rejects keyword arguments if the class being instantiated is map itself:

if (type == &PyMap_Type && !_PyArg_NoKeywords("map", kwds))
    return NULL;

This is basically the C-level equivalent of

def __new__(cls, *args, **kwargs):
    if cls is map and kwargs:
        raise TypeError
    ...

The furthest back I've been able to trace this code is this merge, which includes a change that added checks like this to a bunch of itertools types back when this version of map was still itertools.imap. One of the commit messages is "Bug #1486663: don't reject keyword arguments for subclasses of builtin types.", which seems to be referring to a bug from an old (now-gone?) tracker, but it's not clear why rejecting keyword arguments ever would have been considered a bug - if subclasses want to take keyword arguments a superclass doesn't take, they shouldn't forward those arguments to the superclass __new__.

like image 175
user2357112 supports Monica Avatar answered Nov 03 '22 15:11

user2357112 supports Monica