Cosa sono i "metodi di classe" e i "metodi di istanza", 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 influire su ciò che fa (in genere vengono utilizzate per creare nuove istanze come costruttori alternativi e quindi non sono incredibilmente comuni).
Un "metodo statico" non utilizza alcuna informazione sulla classe o sull'istanza per calcolare ciò che fa. Di solito è solo in classe per comodità. (Pertanto, anche questi non sono molto comuni.)
Una funzione di X
Ricorda la classe di matematica, "y è una funzione di x f(x)
,?" Appliciamolo nel codice:
y = function(x)
Ciò che è implicito 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
"
Cosa sarà y
quando z
è 1
? 2
? 'FooBarBaz'
?
y
non è una funzione di z
, quindi z
può essere qualsiasi cosa e non influire sul risultato della funzione supponendo che la nostra function
sia una funzione pura. (Se accede z
come variabile globale, allora non è una funzione pura - questo è ciò che si intende per purezza funzionale.)
Tieni presente quanto sopra mentre 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 integrato di un metodo di istanza è str.lower:
>>> 'ABC'.lower()
'abc'
str.lower
viene chiamato sull'istanza della stringa e utilizza le informazioni contenute nell'istanza per capire quale nuova stringa restituire.
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 della classe . Accetta la classe come argomento.
Un esempio incorporato è dict.fromkeys
:
>>> dict.fromkeys('ABC')
{'C': None, 'B': None, 'A': None}
La funzione conosce implicitamente la propria classe, la funzione utilizza la classe per influire sull'output della funzione e crea una nuova di quella classe dall'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 utilizza informazioni sulla classe (e non un'istanza di quella classe) per influire sul tipo di classe da restituire.
Metodi statici
Citi un metodo che "non conosce la sua classe" - questo è un metodo statico in Python. È semplicemente collegato per comodità all'oggetto classe. Opzionalmente potrebbe 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 incorporato di un metodo statico è str.maketrans di Python 3.
>>> str.maketrans('abc', 'bca')
{97: 98, 98: 99, 99: 97}
Dato un paio di argomenti, crea un dizionario che non è una funzione della sua classe.
È comodo perché str
è sempre disponibile nello spazio dei nomi globale, quindi puoi usarlo facilmente con la funzione di traduzione:
>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
'bcrbabdbcrb'
In Python 2, devi accedervi dal string
modulo:
>>> '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
Istanziamo:
>>> 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 la classe di solito non è chiamata a chiamare il metodo di istanza, anche se si prevede che chiamerà 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 dell'istanza:
>>> AClass.an_instance_method(instance, 'x', 'y')
('x', 'y', None)