2009-10-14 6 views
43

Следующий код работает:Наследование Python кортеж с несколькими аргументами __init__

class Foo(tuple): 

    def __init__(self, b): 
     super(Foo, self).__init__(tuple(b)) 

if __name__ == '__main__': 
    print Foo([3, 4]) 

$ python play.py 
play.py:4: DeprecationWarning: object.__init__() takes no parameters 
    super(Foo, self).__init__(tuple(b)) 
(3, 4) 

Но не следующее:

class Foo(tuple): 

    def __init__(self, a, b): 
     super(Foo, self).__init__(tuple(b)) 

if __name__ == '__main__': 
    print Foo(None, [3, 4]) 

$ python play.py 
Traceback (most recent call last): 
    File "play.py", line 7, in <module> 
    print Foo(None, [3, 4]) 
TypeError: tuple() takes at most 1 argument (2 given) 

Почему?

ответ

55

Поскольку кортежи являются неизменяемыми, вы должны переопределить __new__ вместо:

python docs

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

Вызывается, чтобы создать новый экземпляр класса cls. __new__() - это статический метод (специально обжатый, поэтому вам не нужно объявить его таким), который принимает класс , экземпляр которого был запрошен в качестве первого аргумента. Остальные аргументы - это те, которые переданы выражению конструктора объекта (вызов класса). Возврат Значение __new__() должно быть новым экземпляром объекта (обычно это пример of cls).

Типичные реализации создать новый экземпляр класса, вызывая __new__() метод в соответствии с суперкласса с помощью super(currentclass, cls).__new__(cls[, ...]) с соответствующими аргументами и затем модификации вновь созданного экземпляра по мере необходимости, прежде чем вернуться его.

__new__() Если возвращает экземпляр cls, то __init__() метод нового экземпляра будет вызываться как __init__(self[, ...]), где само это новый экземпляр, а остальные аргументы такие же, как были приняты к __new__().

__new__() Если не возвращает экземпляра cls, затем __init__() метод нового экземпляра не будет быть вызван.

__new__() предназначен, главным образом, чтобы позволить подклассы неизменных типов (например, int, strtuple или) для настройки создания экземпляра. Также обычно переопределяется в пользовательских метаклассах в , чтобы настроить создание класса.

+0

может кто-нибудь сказать мне, как процитировать весь блок, чтобы двойные подчеркивания не имели значения жирным шрифтом? –

+0

Выберите весь вложенный текст и нажмите значок цитаты (черный значок поверх текстового поля). –

+0

Не работает, но это немного отступало –

39

Чтобы присвоить значение кортежа вам необходимо переопределить __new__ метод:

class Foo(tuple): 

    def __new__ (cls, a, b): 
     return super(Foo, cls).__new__(cls, tuple(b)) 

аргументы, кажется игнорироваться __init__ реализации класса кортежа, но если вам нужно сделать некоторые инициализации вещи вы можете сделать это следующим образом:

class Foo(tuple): 

    def __new__ (cls, a, b): 
     return super(Foo, cls).__new__(cls, tuple(b)) 

    def __init__(self, a, b): 
     self.a=a 
     self.b=b 

if __name__ == '__main__': 
    foo = Foo(None, [3, 4]) 
    print foo 
    print foo.a 
    print foo.b