What are “class methods” and “instance methods”, in Python?
-
Un "metodo di istanza" utilizza le informazioni contenute nell'istanza per capire quale valore restituire (o quale effetto collaterale fare). Questi sono molto comuni.
-
Un "metodo di classe" utilizza le informazioni sulla classe (e non un'istanza di quella classe) per influenzare ciò che fa (sono tipicamente usati per creare nuove istanze come costruttori alternativi, e quindi non sono incredibilmente comune).
-
Un "metodo statico" non utilizza alcuna informazione sulla classe o sull'istanza per calcolare ciò che fa. Di solito è solo nella classe per comodità. (Come tali, anche questi non sono molto comuni).
Funzione di X
Ricorda la classe matematica, "y è una funzione di x, f(x)
?" Applichiamo quello nel codice:
y = function(x)
La conseguenza di quanto sopra è che poiché x
può cambiare, y
può cambiare quando x
cambia. Questo è ciò che si intende quando diciamo che " y
è una funzione di x
"
Che cosa sarà y
quando z
è 1
? %codice%? %codice%?
2
non è una funzione di 'FooBarBaz'
, quindi y
può essere qualsiasi cosa e non influire sul risultato della funzione assumendo che il nostro z
sia una funzione pura. (Se accede a z
come variabile globale, allora non è una funzione pura - questo è ciò che si intende per purezza funzionale.)
Tieni a mente quanto sopra quando leggi le seguenti descrizioni:
Metodi di istanza
Un metodo di istanza è una funzione che è una funzione di un'istanza . La funzione accetta implicitamente l'istanza come argomento e l'istanza viene utilizzata dalla funzione per determinare l'output della funzione.
Un esempio built-in di un metodo di istanza è str.lower:
>>> 'ABC'.lower()
'abc'
function
viene chiamato sull'istanza della stringa e utilizza le informazioni contenute nell'istanza per determinare quale nuova stringa deve essere restituita.
Metodi di classe:
Ricorda, in Python, tutto è un oggetto. Ciò significa che la classe è un oggetto e può essere passata come argomento a una funzione.
Un metodo di classe è una funzione che è una funzione di la classe . Accetta la classe come argomento.
Un esempio incorporato è z
:
>>> dict.fromkeys('ABC')
{'C': None, 'B': None, 'A': None}
La funzione conosce implicitamente la propria classe, la funzione usa la classe per influenzare l'output della funzione, e ne crea una nuova da quella iterabile. Un OrderedDict lo dimostra quando si utilizza lo stesso metodo:
>>> from collections import OrderedDict
>>> OrderedDict.fromkeys('ABC')
OrderedDict([('A', None), ('B', None), ('C', None)])
Il metodo class usa informazioni sulla classe (e non un'istanza di quella classe) per influenzare il tipo di classe da restituire.
Metodi statici
Hai menzionato un metodo che "non conosce la sua classe" - questo è un metodo statico in Python. È semplicemente collegato per comodità all'oggetto di classe. Potrebbe facoltativamente essere una funzione separata in un altro modulo, ma la sua firma di chiamata sarebbe la stessa.
Un metodo statico non è una funzione né della classe né dell'oggetto.
Un esempio built-in di un metodo statico è str.maketrans da Python 3.
>>> str.maketrans('abc', 'bca')
{97: 98, 98: 99, 99: 97}
Dato un paio di argomenti, rende un dizionario che non è una funzione della sua classe.
È comodo perché str.lower
è sempre disponibile nello spazio dei nomi globale, quindi puoi facilmente utilizzarlo con la funzione di traduzione:
>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
'bcrbabdbcrb'
In Python 2, devi accedervi dal modulo dict.fromkeys
:
>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'str' has no attribute 'maketrans'
>>> import string
>>> 'abracadabra'.translate(string.maketrans('abc', 'bca'))
'bcrbabdbcrb'
Esempio
class AClass(object):
"""In Python, a class may have several types of methods:
instance methods, class methods, and static methods
"""
def an_instance_method(self, x, y, z=None):
"""this is a function of the instance of the object
self is the object's instance
"""
return self.a_class_method(x, y)
@classmethod
def a_class_method(cls, x, y, z=None):
"""this is a function of the class of the object
cls is the object's class
"""
return cls.a_static_method(x, y, z=z)
@staticmethod
def a_static_method(x, y, z=None):
"""this is neither a function of the instance or class to
which it is attached
"""
return x, y, z
Facciamo un'istanza:
>>> instance = AClass()
Ora l'istanza può chiamare tutti i metodi:
>>> instance.an_instance_method('x', 'y')
('x', 'y', None)
>>> instance.a_static_method('x', 'y')
('x', 'y', None)
>>> instance.a_class_method('x', 'y')
('x', 'y', None)
Ma di solito la classe non è chiamata a chiamare il metodo di istanza, anche se è previsto chiamare gli altri:
>>> AClass.a_class_method('x', 'y')
('x', 'y', None)
>>> AClass.a_static_method('x', 'y')
('x', 'y', None)
>>> AClass.an_instance_method('x', 'y')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an_instance_method() missing 1 required positional argument: 'y'
Dovresti passare esplicitamente l'istanza per chiamare il metodo di istanza:
>>> AClass.an_instance_method(instance, 'x', 'y')
('x', 'y', None)