Plusieurs constructeurs en python?

Duplication possible:
Qu’est-ce qu’un moyen propre et pythonique d’avoir plusieurs constructeurs en Python?

N’est-il pas possible de définir plusieurs constructeurs en Python, avec des signatures différentes? Si non, quelle est la manière générale de le contourner?

Par exemple, supposons que vous vouliez définir une City classe

Je voudrais pouvoir dire someCity = City() ou someCity = City("Berlin") , où le premier donne juste une valeur de nom par défaut, et le second le définit.

Contrairement à Java, vous ne pouvez pas définir plusieurs constructeurs. Cependant, vous pouvez définir une valeur par défaut si aucune n’est transmise.

 def __init__(self, city="Berlin"): self.city = city 

Si vos signatures diffèrent uniquement par le nombre d’arguments utilisant des arguments par défaut, c’est la bonne façon de le faire. Si vous voulez être capable de transmettre différents types d’arguments, j’essaierais d’éviter l’approche basée sur isinstance mentionnée dans une autre réponse, en utilisant plutôt des arguments de mots clés. Si vous n’utilisez que des arguments de mots-clés, vous pouvez les combiner avec classmethods (le code bzrlib aime cette approche). Ceci est juste un exemple stupide, mais j’espère que vous aurez l’idée:

 class C(object): def __init__(self, fd): # Assume fd is a file-like object. self.fd = fd @classmethod def fromfilename(cls, name): return cls(open(name, 'rb')) # Now you can do: c = C(fd) # or: c = C.fromfilename('a filename') 

Notez que toutes ces méthodes passent toujours par le même __init__ , mais l’utilisation de méthodes de classe peut être beaucoup plus pratique que de devoir se rappeler quelles combinaisons d’arguments de mots-clés pour __init__ fonctionnent.

isinstance est mieux évité car le typage de canard de python rend difficile la détermination du type d’object réellement transmis. Par exemple: si vous voulez prendre un nom de fichier ou un object de type fichier, vous ne pouvez pas utiliser isinstance(arg, file) Il existe de nombreux objects de type fichier qui ne sous-classent pas les file (comme ceux renvoyés par urllib ou SsortingngIO ou …). Il est généralement préférable de demander à l’appelant de vous indiquer explicitement le type d’object concerné, en utilisant différents arguments.

Pour l’exemple que vous avez donné, utilisez les valeurs par défaut:

 class City: def __init__(self, name="Default City Name"): ... ... 

En général, vous avez deux options:

1) Faites des blocs elifelif basés sur le type:

 def __init__(self, name): if isinstance(name, str): ... elif isinstance(name, City): ... ... 

2) Utilisez le typage de canard, c’est-à-dire que l’utilisateur de votre classe est suffisamment intelligent pour l’utiliser correctement. C’est généralement l’option préférée.

Jack M. a raison, fais-le de cette façon:

 >>> class City: ... def __init__(self, city=None): ... self.city = city ... def __repr__(self): ... if self.city: return self.city ... return '' ... >>> c = City('Berlin') >>> print c Berlin >>> c = City() >>> print c >>> 

Le moyen le plus simple consiste à utiliser des arguments de mots-clés:

 class City(): def __init__(self, city=None): pass someCity = City(city="Berlin") 

C’est un truc assez basique, peut-être regarder les docs python ?