Ecco quello che mi sento di raccomandare:
class Team(object):
def __init__(self, name=None, logo=None, members=0):
self.name = name
self.logo = logo
self.members = members
team = Team("Oscar", "http://...", 10)
team2 = Team()
team2.name = "Fred"
team3 = Team(name="Joe", members=10)
Alcune note su questo.
0) Ho dichiarato che il team eredita da object
. Questo rende la squadra una "classe di nuovo stile"; questa è stata una pratica raccomandata in Python da quando è stata introdotta in Python 2.2. (In Python 3.0 e versioni successive, le classi sono sempre "di nuovo stile" anche se si omette la notazione (object)
, ma l'annotazione non fa danno e rende esplicita l'ereditarietà.) Ecco uno StackOverflow discussion di classi di nuovo stile.
1) Non è necessario, ma ho fatto in modo che l'inizializzatore prenda argomenti facoltativi in modo da poter inizializzare l'istanza su una riga, come ho fatto con team
e team3
. Questi argomenti sono denominati, quindi è possibile fornire valori come parametri posizionali (come con team
) oppure è possibile utilizzare il modulo argument=
come ho fatto con team3
. Quando si specifica esplicitamente il nome degli argomenti, è possibile specificare argomenti in qualsiasi ordine.
2) Se fosse necessario disporre di funzioni getter e setter, forse per controllare qualcosa, in Python è possibile dichiarare funzioni di metodo speciali. Questo è ciò che intendeva Martin v. Löwis quando diceva "descrittori di proprietà". In Python, è generalmente considerata una buona pratica semplicemente assegnare a variabili membro, e semplicemente fare riferimento a loro per recuperarle, perché è sempre possibile aggiungere i descrittori di proprietà in un secondo momento in caso di necessità. (E se li avete mai bisogno, quindi il codice è meno ingombrante e si ha meno tempo per scrivere Bonus.!)
Ecco un buon collegamento su descrittori di proprietà: http://adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/
3) E 'davvero non importa se si specificano i valori come parte della chiamata a Team()
o se li si inserisce nell'istanza della classe in un secondo momento. L'istanza della classe finale alla quale farai sarà identica.
team = Team("Joe", "http://example.com", 1)
team2 = Team()
team2.name = "Joe"
team2.logo = "http://example.com"
team2.members = 1
print team.__dict__ == team2.__dict__
Quanto sopra verrà stampato True
.(Si può facilmente sovraccaricare l'operatore ==
per Team
casi, e rendere Python fare la cosa giusta quando dici team == team2
, ma questo non avviene per impostazione predefinita.)
EDIT: ho lasciato fuori una cosa al di sopra risposta, e mi piacerebbe aggiungerlo ora. Se si esegue la funzione argomento opzionale nella funzione __init__()
, è necessario prestare attenzione se si desidera fornire un "mutabile" come argomento facoltativo.
I numeri interi e le stringhe sono "immutabili". Non puoi mai cambiarli sul posto; ciò che accade invece è che Python crea un nuovo oggetto e sostituisce quello che avevi prima.
Elenchi e dizionari sono "mutabili". Puoi mantenere lo stesso oggetto per sempre, aggiungendolo e cancellandolo.
x = 3 # the name "x" is bound to an integer object with value 3
x += 1 # the name "x" is rebound to a different integer object with value 4
x = [] # the name "x" is bound to an empty list object
x.append(1) # the 1 is appended to the same list x already had
La cosa fondamentale da sapere: gli argomenti facoltativi vengono valutati una sola volta, quando la funzione viene compilata. Pertanto, se si passa un argomento mutabile come argomento facoltativo nello __init__()
per la classe, ciascuna istanza della classe condivide un oggetto mutabile. Questo non è quasi mai quello che vuoi.
class K(object):
def __init__(self, lst=[]):
self.lst = lst
k0 = K()
k1 = K()
k0.lst.append(1)
print k0.lst # prints "[1]"
print k1.lst # also prints "[1]"
k1.lst.append(2)
print k0.lst # prints "[1, 2]"
La soluzione è molto semplice:
class K(object):
def __init__(self, lst=None):
if lst is None:
self.lst = [] # bind lst with a new, empty list
else:
self.lst = lst # bind lst with provided list
k0 = K()
k1 = K()
k0.lst.append(1)
print k0.lst # prints "[1]"
print k1.lst # print "[]"
Questo business di utilizzare un valore di argomento di default di None
, poi prova che l'argomento passato is None
, si qualifica come un modello di progettazione di Python, o almeno di un idioma dovresti padroneggiare.
Mi piacerebbe suggerire che qualcuno cambi il titolo in qualcosa che è meglio per la ricerca futura. Qualcosa come "Il miglior modo per definire una classe in Python". – steveha
@steveha: Forse anche se la mia vera domanda era, come scrivo questo in python ... che dire ... – OscarRyz