Quello che mi ha appena colpito, proveniente da Ruby, è che un cosiddetto metodo di classe e un cosiddetto metodo di istanza sono solo una funzione con significato semantico applicata al suo primo parametro, che viene silenziosamente passato quando la funzione viene chiamata come metodo di un oggetto (cioè obj.meth()
).
Normalmente quell'oggetto deve essere un'istanza ma il @classmethod
decoratore del metodo cambia le regole per passare una classe. Puoi chiamare un metodo di classe su un'istanza (è solo una funzione) - il primo argomento sarà la sua classe.
Poiché è solo una funzione , può essere dichiarata una sola volta in un determinato ambito (ad es. class
Definizione). Se segue quindi, come sorpresa per un Rubyist, non puoi avere un metodo di classe e un metodo di istanza con lo stesso nome .
Considera questo:
class Foo():
def foo(x):
print(x)
Puoi chiamare foo
un'istanza
Foo().foo()
<__main__.Foo instance at 0x7f4dd3e3bc20>
Ma non in una classe:
Foo.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)
Ora aggiungi @classmethod
:
class Foo():
@classmethod
def foo(x):
print(x)
Chiamare un'istanza ora passa la sua classe:
Foo().foo()
__main__.Foo
come fare una lezione:
Foo.foo()
__main__.Foo
È solo la convenzione a dettare che usiamo self
per quel primo argomento su un metodo di istanza e cls
su un metodo di classe. Non ho usato né qui per illustrare che è solo un argomento. In Ruby, self
è una parola chiave.
Contrasto con Ruby:
class Foo
def foo()
puts "instance method #{self}"
end
def self.foo()
puts "class method #{self}"
end
end
Foo.foo()
class method Foo
Foo.new.foo()
instance method #<Foo:0x000000020fe018>
Il metodo della classe Python è solo una funzione decorata e puoi usare le stesse tecniche per creare i tuoi decoratori . Un metodo decorato avvolge il metodo reale (nel caso in @classmethod
cui passi l'argomento di classe aggiuntivo). Il metodo sottostante è ancora lì, nascosto ma ancora accessibile .
nota a piè di pagina: l'ho scritto dopo che uno scontro di nomi tra una classe e un metodo di istanza ha suscitato la mia curiosità. Sono ben lungi dall'essere un esperto di Python e vorrei commenti se qualcosa di tutto ciò è sbagliato.