2017-02-23 3 views
2

J'essaye de créer une sous-classe de tuple qui se comporte dans tous les aspects comme un tuple normal à l'exception que je l'initialise avec une chaîne qui est automatiquement divisée d'abord par le constructeur (je veux aussi son __str__() pour rejoindre à nouveau, mais ce n'est pas le problème ici).Sous-classe Tuple avec str pour init

Je pensais que ce soit droite vers l'avant et comme celui-ci ont essayé:

class C(tuple): 
    def __init__(self, text): 
    super(C, self).__init__(text.split(':')) 

    def __str__(self): 
    return '[%s]' % ':'.join(self) 

c = C('one:two:three') # I expect this to be like ('one', 'two', 'three') 

J'essaie donc de passer un text (un str), diviser cela et appeler le constructeur de mon superclasse avec le résultat. Je m'attendais à obtenir un résultat comme pour tuple([ 'one', 'two', 'three' ]), je. e. un tuple de mots: ('one', 'two', 'three').

Mais à la place, je reçois un tuple de caractères, je. e. pour l'entrée 'one:two:three' j'obtiens un ('o', 'n', 'e', ':', 't', 'w', 'o', ':', 't', 'h', 'r', 'e', 'e') qui est exactement le résultat que j'obtiens quand j'appelle tuple('one:two:three'). J'ai débuggé la situation et j'ai découvert que mon code est correctement exécuté (mon __init__() est appelé et appelle l'autre __init__() avec les valeurs correctes). J'ai également essayé de remplacer la construction super par un tuple.__init__(self, text.split(':')) concret, mais cela n'a rien changé. J'ai également essayé de passer un tuple au lieu du list créé par split(), également aucun changement. En fait, l'appel du super __init__() ne semble pas avoir d'effet. L'interpréteur initialise toujours le tuple avec la chaîne que je passe à l'origine.

Ai-je raté quelque chose? Pourquoi cela ne fonctionne-t-il pas comme prévu? Comment puis-je créer une classe C qui est une sous-classe de tuple et que je peux initialiser en appelant C('one:two:three') pour obtenir une instance de C qui est un tuple comme ('one', 'two', 'three')?

+0

Quelle version utilisez-vous? Je reçois 'TypeError: object .__ init __() ne prend aucun paramètre sur 3.5 –

+0

@StevenSummers: J'utilise Python 2.7 dans ce projet mais je suis curieux: Avez-vous vraiment ce message d'erreur à propos de' object .__ init __() ' ne prend aucun argument lorsque vous héritez 'tuple' dans 3.5? – Alfe

+0

C'est ce que je reçois lors de l'exécution de votre code, même pour 3.4 et 3.6 –

Répondre

2

Depuis tuples sont immuables, utilisez __new__ au lieu de __init__:

class C(tuple): 
    def __new__(cls, text): 
     return super(C, cls).__new__(cls, text.split(':')) 

    def __str__(self): 
     return '[%s]' % ':'.join(self) 

c = C('one:two:three') 
print(c) 
print(list(c)) 
+1

Pour quiconque se demandant quelle est la différence entre '__init__' et' __new__' ce post m'a vraiment aidé http://stackoverflow.com/questions/4859129/python- et-python-c-api-nouveau-contre-init – Ramast