Dichiarare più costruttori in python

Afelium (770 points)
3 11 18
asked Nov 27, 2020 in Programmare in Python by Afelium (770 points)
edited Nov 28, 2020 by andrea.sterbini

Non ricordo se è stato già detto a lezione, ma mi pare di aver capito che in python non è possibile fornire più di un costruttore (__init__ ) per classe, mentre in altri linguaggi come C# o Java se ne possono dichiarare molteplici purchè abbiano una firma diversa. Un workaround per alcuni casi potrebbe essere mettere dei parametri di default con valore None, ma mi domandavo se esiste una maniera piu "pythonica"

EDIT: ho spostato il post nel forum italiano @andrea.sterbini, e assegnato un pesante dislike no perchè avete sbagliato forum

5 Answers

b
benjamin (2490 points)
0 6 21
answered Nov 27, 2020 by benjamin (2,490 points)
Penso che un modo potrebbe essere sfruttare l'eredità delle classi.

Sostanzialmente quando definisci una classe puoi farr così : class Name (parent) :

... Dove name è il nome della tua nuova classe "figlio" che avrà gli stessi metodi e attributi della classe parent. Quando definisci il metodo __init__ nela classe figlio ( "Name" In questo caso) verrà eseguito quest'ultimo piuttosto che lo stesso metodo nella classe genitore.

Così puoi avere costruttori diversi ma mantenendo gli stessi metodi.

Spero si sia capito... In ogni caso una veloce ricerca su Google su questo argomento e vai
commented Nov 28, 2020 by Claudio.DiCiccio (2,770 points)
Auf Englisch, bitte.

Mit freundlichen Grüßen,
CDC
S
Silktrader (2550 points)
1 6 16
answered Nov 27, 2020 by Silktrader (2,550 points)

Ci sono varie alternative, tutte eccessivamente complesse, visto il contesto:

  1. se l'oggetto da creare risulta molto complicato, puoi usare quelle si chiamano "creational patterns" — "static factory", "builder pattern", etc.
  2. puoi più semplicemente scrivere dei metodi che ritornano l'oggetto stesso che vuoi creare e chiamarli a catena
  3. puoi passare oggetti complessi ad __init__ ed agire a seconda del tipo ricevuto con degli ineleganti if

Se non hai timore di lasciare l'oggetto in uno stato "non finito" qualcosa del genere viene usato spesso:

Car().MountChassis(SF1000).AddEngine(V6).AddPilot(Leclerc)

Generalmente viene sconsigliato di passare tanti argomenti ad __init__. Dargli cinque o sei "default" diventa presto caotico.

commented Nov 28, 2020 by Claudio.DiCiccio (2,770 points)
Auf Englisch, bitte.

Mit freundlichen Grüßen,
CDC
S
Silktrader (2550 points)
1 6 16
commented Nov 28, 2020 by Silktrader (2,550 points)
Cher Professeur,

Message reçu et compris! L'auteur de la question est un étudiant du cours Italien qui s'est planté de section. Le Prof. Sterbini, toujours vigilant, régulièrement balaye ce genre d'erreur du coté Italien, comme dans ce cas: https://q2a.di.uniroma1.it/19232/una-lista-come-rappresentata-su-disco-con-indice-allinizio?course=programmare-in-python/fondamenti-di-programmazione-20-21

Respectueusement, mes amitiés,

CGT
G
Giordano_Dionisi (3100 points)
12 38 58
answered Nov 27, 2020 by Giordano_Dionisi (3,100 points)
I think that you are in the wrong forum, because this is the English version... So i think that you have to post question in English for the other students
Dario_loi (1710 points)
0 3 10
answered Nov 27, 2020 by Dario_loi (1,710 points)
I think you can only have one object for every given object, since it is the function that gets called on that object's initialization, having two would just be confusing.

If you are looking for constructor overloading, you could exploit inheritance as my colleagues have explained.

If you however are just looking for an aesthetically pleasing way of not doing huge amounts of calculations in your __init__ method, sticking to the declaration of attributes, what you could do is define a bunch of "constructor helper" modules, for an example, if you have a geometrical object and you don't want to straight up compute things such as area and perimeter in the init, you could define methods to calculate those and then call them into your contructor, having them initialize those variables inside themselves, or if you prefer, have then return values that then get assigned into attributes in the __init__, which would be a more OOP-way

If the methods are appropriately named (calculateArea) the reader should immediately get what their purpose is without having to look at all the ugly calculations, that are obfuscated inside them.

this way you can have a single constructor that then branches in calling multiple other methods, which is something close to what you asked, I think.
answered Nov 28, 2020 by Claudio.DiCiccio (2,770 points)
Sehr geehrter Herr,

Bitte schreiben Sie Ihre Beiträge auf Englisch, damit sie für alle verständlich sind. Vielen Dank im Voraus für Ihre Zusammenarbeit.

Mit freundlichen Grüßen,
CDC