Python 3.7
Utilisez le paramètre par défaut .
>>> from collections import namedtuple
>>> fields = ('val', 'left', 'right')
>>> Node = namedtuple('Node', fields, defaults=(None,) * len(fields))
>>> Node()
Node(val=None, left=None, right=None)
Ou mieux encore, utilisez la nouvelle bibliothèque de classes de données , qui est beaucoup plus agréable que namedtuple.
>>> from dataclasses import dataclass
>>> from typing import Any
>>> @dataclass
... class Node:
... val: Any = None
... left: 'Node' = None
... right: 'Node' = None
>>> Node()
Node(val=None, left=None, right=None)
Avant Python 3.7
Définissez Node.__new__.__defaults__
les valeurs par défaut.
>>> from collections import namedtuple
>>> Node = namedtuple('Node', 'val left right')
>>> Node.__new__.__defaults__ = (None,) * len(Node._fields)
>>> Node()
Node(val=None, left=None, right=None)
Avant Python 2.6
Définissez Node.__new__.func_defaults
les valeurs par défaut.
>>> from collections import namedtuple
>>> Node = namedtuple('Node', 'val left right')
>>> Node.__new__.func_defaults = (None,) * len(Node._fields)
>>> Node()
Node(val=None, left=None, right=None)
Ordre
Dans toutes les versions de Python, si vous définissez moins de valeurs par défaut qu'il n'en existe dans le tuple nommé, les valeurs par défaut sont appliquées aux paramètres les plus à droite. Cela vous permet de conserver certains arguments comme arguments requis.
>>> Node.__new__.__defaults__ = (1,2)
>>> Node()
Traceback (most recent call last):
...
TypeError: __new__() missing 1 required positional argument: 'val'
>>> Node(3)
Node(val=3, left=1, right=2)
Wrapper pour Python 2.6 à 3.6
Voici un wrapper pour vous, qui vous permet même (facultativement) de définir les valeurs par défaut sur autre chose que None
. Cela ne prend pas en charge les arguments requis.
import collections
def namedtuple_with_defaults(typename, field_names, default_values=()):
T = collections.namedtuple(typename, field_names)
T.__new__.__defaults__ = (None,) * len(T._fields)
if isinstance(default_values, collections.Mapping):
prototype = T(**default_values)
else:
prototype = T(*default_values)
T.__new__.__defaults__ = tuple(prototype)
return T
Exemple:
>>> Node = namedtuple_with_defaults('Node', 'val left right')
>>> Node()
Node(val=None, left=None, right=None)
>>> Node = namedtuple_with_defaults('Node', 'val left right', [1, 2, 3])
>>> Node()
Node(val=1, left=2, right=3)
>>> Node = namedtuple_with_defaults('Node', 'val left right', {'right':7})
>>> Node()
Node(val=None, left=None, right=7)
>>> Node(4)
Node(val=4, left=None, right=7)
Node
qu'il est. Pourquoi convertir en tuple nommé?Node
classes actuelles et autres sont de simples objets de valeur contenant des données avec un tas de champs différents (Node
c'est juste l'un d'entre eux). Ces déclarations de classe ne sont rien de plus que le bruit de ligne à mon humble avis et ont donc voulu les supprimer. Pourquoi entretenir quelque chose qui n'est pas nécessaire? :).debug_print()
méthode qui parcourt l'arbre et l'imprime?BinaryTree
classe.Node
et d'autres détenteurs de données ne nécessitent pas de telles méthodes spéciales, étant donné que les tuples nommés ont une représentation__str__
et une__repr__
représentation décentes . :)