Python: extending int and MRO for __init__

2019-06-15 17:59发布

In Python, I'm trying to extend the builtin 'int' type. In doing so I want to pass in some keywoard arguments to the constructor, so I do this:

class C(int):
     def __init__(self, val, **kwargs):
         super(C, self).__init__(val)
         # Do something with kwargs here...

However while calling C(3) works fine, C(3, a=4) gives:

'a' is an invalid keyword argument for this function` 

and C.__mro__ returns the expected:

(<class '__main__.C'>, <type 'int'>, <type 'object'>)

But it seems that Python is trying to call int.__init__ first... Anyone know why? Is this a bug in the interpreter?

3条回答
乱世女痞
2楼-- · 2019-06-15 18:15

The docs for the Python data model advise using __new__:

object.new(cls[, ...])

new() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

Something like this should do it for the example you gave:

class C(int):

    def __new__(cls, val, **kwargs):
        inst = super(C, cls).__new__(cls, val)
        inst.a = kwargs.get('a', 0)
        return inst
查看更多
地球回转人心会变
3楼-- · 2019-06-15 18:18

What everyone else (so far) said. Int are immutable, so you have to use new.

Also see (the accepted answers to):

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-06-15 18:21

You should be overriding "__new__", not "__init__" as ints are immutable.

查看更多
登录 后发表回答