Python: расширение int и MRO для __init__

В Python я пытаюсь расширить встроенный тип int. При этом я хочу передать конструктору некоторые ключевые аргументы, поэтому я делаю следующее:

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

Однако при вызове C(3) работает нормально, C(3, a=4) дает:

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

и C.__mro__ возвращает ожидаемое:

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

Но кажется, что Python сначала пытается вызвать int.__init__... Кто-нибудь знает, почему? Это ошибка интерпретатора?


person Community    schedule 26.07.2009    source источник


Ответы (3)


Документы для модели данных Python советуют использовать __new__:

объект.новый(cls[, ...])

new() в основном предназначен для того, чтобы позволить подклассам неизменяемых типов (например, int, str или tuple) настраивать создание экземпляров. Он также обычно переопределяется в пользовательских метаклассах, чтобы настроить создание класса.

Что-то вроде этого должно сделать это для примера, который вы привели:

class C(int):

    def __new__(cls, val, **kwargs):
        inst = super(C, cls).__new__(cls, val)
        inst.a = kwargs.get('a', 0)
        return inst
person Jarret Hardie    schedule 26.07.2009

Вы должны переопределить "__new__", а не "__init__", поскольку целые числа неизменяемы.

person David Raznick    schedule 26.07.2009

То, что все остальные (пока) сказали. Int неизменяемы, поэтому вам нужно использовать new.

Также см. (принятые ответы на):

person Arkady    schedule 26.07.2009