python decorator - Qual è la differenza tra @staticmethod e @classmethod?




call from (20)

Fondamentalmente @classmethod rende un metodo il cui primo argomento è la classe da cui viene chiamato (piuttosto che l'istanza di classe), @staticmethod non ha argomenti impliciti.

Qual è la differenza tra una funzione decorata con @staticmethod e una decorata con @classmethod ?


Analizzare @staticmethod fornendo letteralmente informazioni diverse.

Un metodo normale di una classe è un metodo dinamico implicito che prende l'istanza come primo argomento.
Al contrario, un metodo statico non prende l'istanza come primo argomento, quindi viene chiamato 'statico' .

Un metodo statico è in effetti una funzione normale uguale a quella di una definizione di classe.
È fortunatamente raggruppato nella classe solo per stare più vicino dove è applicato, o si potrebbe scorrere per trovarlo.


La guida definitiva su come usare i metodi statici, di classe o astratti in Python è un buon collegamento per questo argomento, e lo riassume come segue.

@staticmethod funzione @staticmethod non è altro che una funzione definita all'interno di una classe. È callabile senza prima istanziare la classe. La sua definizione è immutabile per via ereditaria.

  • Python non deve istanziare un metodo vincolato per l'oggetto.
  • Facilita la leggibilità del codice e non dipende dallo stato dell'oggetto stesso;

@classmethod funzione @classmethod anche essere richiamata senza @classmethod un'istanza della classe, ma la sua definizione segue la classe Sub, non la classe Parent, tramite l'ereditarietà, può essere sovrascritta dalla sottoclasse. Questo perché il primo argomento per la funzione @classmethod deve sempre essere cls (classe).

  • Metodi di fabbrica , che sono usati per creare un'istanza per una classe usando per esempio una sorta di pre-elaborazione.
  • Metodi statici che chiamano metodi statici : se dividi un metodo statico in diversi metodi statici, non devi codificare il nome della classe ma usare i metodi di classe

Penso che una domanda migliore sia "Quando useresti @classmethod vs @staticmethod?"

@classmethod consente un facile accesso ai membri privati ​​associati alla definizione della classe. questo è un ottimo modo per fare singleton o esistono classi factory che controllano il numero di istanze degli oggetti creati.

@staticmethod fornisce guadagni marginali delle prestazioni, ma devo ancora vedere un uso produttivo di un metodo statico all'interno di una classe che non può essere raggiunto come funzione autonoma al di fuori della classe.


Forse un po 'di codice di esempio aiuterà: Notare la differenza nelle firme di chiamata di foo , class_foo e static_foo :

class A(object):
    def foo(self,x):
        print "executing foo(%s,%s)"%(self,x)

    @classmethod
    def class_foo(cls,x):
        print "executing class_foo(%s,%s)"%(cls,x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)"%x    

a=A()

Sotto è il solito modo in cui un'istanza dell'oggetto chiama un metodo. L'istanza dell'oggetto, a , viene passata implicitamente come primo argomento.

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)

Con classmethods , la classe dell'istanza dell'oggetto viene passata implicitamente come primo argomento anziché come self .

a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

Puoi anche chiamare class_foo usando la classe. In effetti, se si definisce qualcosa come un metodo di classe, è probabilmente perché si intende richiamarlo dalla classe piuttosto che da un'istanza di classe. A.foo(1) avrebbe generato un A.class_foo(1) , ma A.class_foo(1) funziona perfettamente:

A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

Un uso che le persone hanno trovato per i metodi di classe è la creazione di costrutti alternativi ereditabili .

Con staticmethods , né self (l'istanza dell'oggetto) né cls (la classe) vengono passati implicitamente come primo argomento. Si comportano come semplici funzioni, tranne che puoi chiamarle da un'istanza o dalla classe:

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

I metodi statici vengono utilizzati per raggruppare le funzioni che presentano una connessione logica con una classe alla classe.

foo è solo una funzione, ma quando si chiama a.foo non si ottiene semplicemente la funzione, si ottiene una versione "parzialmente applicata" della funzione con l'istanza dell'oggetto associata come primo argomento alla funzione. foo aspetta 2 argomenti, mentre a.foo si aspetta solo 1 argomento.

a è legato a foo . Questo è ciò che si intende per "legato" sotto:

print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

Con a.class_foo , a non è associato a class_foo , piuttosto la classe A è associata a class_foo .

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

Qui, con un metodo statico, anche se si tratta di un metodo, a.static_foo restituisce semplicemente una buona funzione "ole" senza alcun argomento associato. static_foo aspetta un argomento e a.static_foo aspetta anche 1 argomento.

print(a.static_foo)
# <function static_foo at 0xb7d479cc>

E ovviamente accade la stessa cosa quando si chiama static_foo con la classe A

print(A.static_foo)
# <function static_foo at 0xb7d479cc>

Lasciatemi dire la somiglianza tra un metodo decorato con @classmethod vs @staticmethod prima.

Somiglianza: entrambi possono essere chiamati sulla classe stessa, piuttosto che solo sull'istanza della classe. Quindi, entrambi in un certo senso sono metodi della classe .

Differenza: un classmethod riceverà la classe stessa come primo argomento, mentre un metodo statico no.

Quindi, un metodo statico non è, in un certo senso, legato alla classe stessa e si trova solo lì perché potrebbe avere una funzionalità correlata.

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)

Un'altra considerazione rispetto a staticmethod vs classmethod arriva con l'ereditarietà. Dì che hai la seguente classe:

class Foo(object):
    @staticmethod
    def bar():
        return "In Foo"

E poi vuoi sostituire la bar() in una classe figlia:

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"

Questo funziona, ma si noti che ora l'implementazione bar() nella classe figlio ( Foo2 ) non può più trarre vantaggio da qualcosa di specifico per quella classe. Ad esempio, dire che Foo2 aveva un metodo chiamato magic() che si desidera utilizzare nell'implementazione di Foo2 di bar() :

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"
    @staticmethod
    def magic():
        return "Something useful you'd like to use in bar, but now can't" 

La soluzione sarebbe chiamare Foo2.magic() in bar() , ma poi ti stai ripetendo (se il nome di Foo2 cambia, dovrai ricordarti di aggiornare quel metodo bar() ).

Per me, questa è una leggera violazione del principio di apertura / chiusura , poiché una decisione presa in Foo impatto sulla capacità di refactoring di codice comune in una classe derivata (cioè è meno aperta all'estensione). Se bar() fosse un classmethod , andrebbe bene:

class Foo(object):
    @classmethod
    def bar(cls):
        return "In Foo"

class Foo2(Foo):
    @classmethod
    def bar(cls):
        return "In Foo2 " + cls.magic()
    @classmethod
    def magic(cls):
        return "MAGIC"

print Foo2().bar()

Dà: In Foo2 MAGIC


Il mio contributo dimostra la differenza tra @classmethod , @staticmethod e i metodi di istanza, incluso il modo in cui un'istanza può chiamare indirettamente un @staticmethod . Ma invece di chiamare indirettamente un @staticmethod da un'istanza, renderlo privato potrebbe essere più "pythonic". Ottenere qualcosa da un metodo privato non è dimostrato qui, ma è fondamentalmente lo stesso concetto.

#!python3

from os import system
system('cls')
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

class DemoClass(object):
    # instance methods need a class instance and
    # can access the instance through 'self'
    def instance_method_1(self):
        return 'called from inside the instance_method_1()'

    def instance_method_2(self):
        # an instance outside the class indirectly calls the static_method
        return self.static_method() + ' via instance_method_2()'

    # class methods don't need a class instance, they can't access the
    # instance (self) but they have access to the class itself via 'cls'
    @classmethod
    def class_method(cls):
        return 'called from inside the class_method()'

    # static methods don't have access to 'cls' or 'self', they work like
    # regular functions but belong to the class' namespace
    @staticmethod
    def static_method():
        return 'called from inside the static_method()'
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''

# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()

# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''

# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a @staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''

# call class_method()
print(democlassObj.class_method() + '\n')
'''  called from inside the class_method() '''

# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''

"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""

Per decidere se usare @staticmethod o @classmethod devi guardare all'interno del tuo metodo. Se il tuo metodo accede ad altre variabili / metodi nella tua classe, usa @classmethod . D'altra parte, se il tuo metodo non tocca altre parti della classe, allora usa @staticmethod.

class Apple:

    _counter = 0

    @staticmethod
    def about_apple():
        print('Apple is good for you.')

        # note you can still access other member of the class
        # but you have to use the class instance 
        # which is not very nice, because you have repeat yourself
        # 
        # For example:
        # @staticmethod
        #    print('Number of apples have been juiced: %s' % Apple._counter)
        #
        # @classmethod
        #    print('Number of apples have been juiced: %s' % cls._counter)
        #
        #    @classmethod is especially useful when you move your function to other class,
        #       you don't have to rename the class reference 

    @classmethod
    def make_apple_juice(cls, number_of_apples):
        print('Make juice:')
        for i in range(number_of_apples):
            cls._juice_this(i)

    @classmethod
    def _juice_this(cls, apple):
        print('Juicing %d...' % apple)
        cls._counter += 1

Ho iniziato a imparare il linguaggio di programmazione con C ++ e poi con Java e poi con Python, quindi anche questa domanda mi ha infastidito molto, fino a quando ho capito il semplice utilizzo di ciascuno.

Metodo di classe: Python a differenza di Java e C ++ non ha overloading del costruttore. E così per raggiungere questo obiettivo potresti usare classmethod . L'esempio seguente spiegherà questo

Consideriamo una classe Person che prende due argomenti first_name e last_name e crea l'istanza di Person.

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

Ora, se il requisito arriva dove è necessario creare una classe usando solo un solo nome, solo un first_name , non si può fare qualcosa del genere in python.

Questo ti darà un errore quando tenterai di creare un oggetto (istanza).

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __init__(self, first_name):
        self.first_name = first_name

Tuttavia, è possibile ottenere la stessa cosa usando @classmethod come indicato di seguito

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @classmethod
    def get_person(cls, first_name):
        return cls(first_name, "")

Metodo statico : questo è piuttosto semplice, non è legato all'istanza o alla classe e puoi semplicemente chiamarlo usando il nome della classe.

Quindi, diciamo nell'esempio sopra, hai bisogno di una convalida che first_name non debba superare i 20 caratteri, puoi semplicemente farlo.

@staticmethod  
def validate_name(name):
    return len(name) <= 20

e potresti semplicemente chiamare usando il nome della classe

Person.validate_name("Gaurang Shah")

I metodi di classe, come suggerisce il nome, vengono utilizzati per apportare modifiche alle classi e non agli oggetti. Per apportare modifiche alle classi, modificheranno gli attributi della classe (non gli attributi dell'oggetto), poiché è così che si aggiornano le classi. Questo è il motivo per cui i metodi di classe prendono la classe (convenzionalmente indicata con 'cls') come primo argomento.

class A(object):
    m=54

    @classmethod
    def class_method(cls):
        print "m is %d" % cls.m

I metodi statici, d'altra parte, sono usati per eseguire funzionalità che non sono legate alla classe, cioè non leggeranno o scrivono variabili di classe. Quindi, i metodi statici non considerano le classi come argomenti. Vengono utilizzati in modo che le classi possano eseguire funzionalità che non sono direttamente correlate allo scopo della classe.

class X(object):
    m=54 #will not be referenced

    @staticmethod
    def static_method():
        print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."

Qual è la differenza tra @staticmethod e @classmethod in Python?

Potresti aver visto il codice Python come questo pseudocodice, che dimostra le firme dei vari tipi di metodo e fornisce una docstring per spiegare ciascuno:

class Foo(object):

    def a_normal_instance_method(self, arg_1, kwarg_2=None):
        '''
        Return a value that is a function of the instance with its
        attributes, and other arguments such as arg_1 and kwarg2
        '''

    @staticmethod
    def a_static_method(arg_0):
        '''
        Return a value that is a function of arg_0. It does not know the 
        instance or class it is called from.
        '''

    @classmethod
    def a_class_method(cls, arg1):
        '''
        Return a value that is a function of the class and other arguments.
        respects subclassing, it is called with the class it is called from.
        '''

Il metodo di istanza normale

Innanzitutto spiegherò a_normal_instance_method . Questo è precisamente chiamato " metodo di istanza ". Quando viene utilizzato un metodo di istanza, viene utilizzato come funzione parziale (al contrario di una funzione totale, definita per tutti i valori visualizzati nel codice sorgente) che, quando utilizzato, il primo degli argomenti è predefinito come l'istanza del oggetto, con tutti i suoi attributi dati. Ha l'istanza dell'oggetto ad esso associato e deve essere chiamato da un'istanza dell'oggetto. In genere, accederà a vari attributi dell'istanza.

Ad esempio, questa è un'istanza di una stringa:

', '

se usiamo il metodo instance, ci join su questa stringa, per unire un altro iterabile, è ovviamente una funzione dell'istanza, oltre ad essere una funzione della lista iterabile, ['a', 'b', 'c'] :

>>> ', '.join(['a', 'b', 'c'])
'a, b, c'

Metodi rilegati

I metodi di istanza possono essere associati tramite una ricerca punteggiata da utilizzare in un secondo momento.

Ad esempio, questo associa il metodo str.join ':' :

>>> join_with_colons = ':'.join 

E più tardi possiamo usare questo come funzione che ha già il primo argomento associato ad esso. In questo modo, funziona come una funzione parziale sull'istanza:

>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'

Metodo statico

Il metodo statico non accetta l'istanza come argomento.

È molto simile a una funzione a livello di modulo.

Tuttavia, una funzione di livello modulo deve vivere nel modulo ed essere importata in modo speciale in altri luoghi in cui viene utilizzata.

Se è collegato all'oggetto, tuttavia, seguirà l'oggetto comodamente attraverso l'importazione e l'ereditarietà.

Un esempio di un metodo statico è str.maketrans , spostato dal modulo string in Python 3. Rende una tabella di conversione adatta al consumo da str.translate . Sembra piuttosto stupido quando viene utilizzato da un'istanza di una stringa, come illustrato di seguito, ma importare la funzione dal modulo string è piuttosto maldestro, ed è bello poterlo chiamare dalla classe, come in str.maketrans

# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}

In python 2, devi importare questa funzione dal modulo di stringa sempre meno utile:

>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'

Metodo di classe

Un metodo di classe è simile a un metodo di istanza in quanto accetta un primo argomento implicito, ma invece di prendere l'istanza, accetta la classe. Spesso questi sono usati come costruttori alternativi per un migliore utilizzo semantico e supporteranno l'ereditarietà.

L'esempio più canonico di un metodo di classe incorporato è dict.fromkeys . È usato come costruttore alternativo di dict, (adatto per quando sai quali sono le tue chiavi e vuoi un valore predefinito per loro).

>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}

Quando eseguiamo la sottoclasse di dict, possiamo usare lo stesso costruttore, che crea un'istanza della sottoclasse.

>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>

Vedi il codice sorgente dei panda per altri esempi simili di costruttori alternativi, e vedi anche la documentazione ufficiale su Python su classmethod e staticmethod .


Here un breve articolo su questa domanda

La funzione @staticmethod non è altro che una funzione definita all'interno di una classe. È callabile senza prima istanziare la classe. La sua definizione è immutabile per via ereditaria.

La funzione @classmethod può anche essere richiamata senza creare un'istanza della classe, ma la sua definizione segue la classe Sub, non la classe Parent, tramite l'ereditarietà. Questo perché il primo argomento per la funzione @classmethod deve sempre essere cls (classe).


Documenti Python ufficiali:

@classmethod

Un metodo di classe riceve la classe come primo argomento implicito, proprio come un metodo di istanza riceve l'istanza. Per dichiarare un metodo di classe, usa questo idioma:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ... 

Il modulo @classmethod è un decorator di funzioni: per i dettagli vedere la descrizione delle definizioni di funzione nelle definizioni di funzione .

Può essere chiamato sulla classe (come Cf() ) o su un'istanza (come C().f() ). L'istanza viene ignorata tranne che per la sua classe. Se viene chiamato un metodo di classe per una classe derivata, l'oggetto classe derivata viene passato come primo argomento implicito.

I metodi di classe sono diversi dai metodi statici C ++ o Java. Se vuoi quelli, vedi staticmethod() in questa sezione.

@staticmethod

Un metodo statico non riceve un primo argomento implicito. Per dichiarare un metodo statico, usa questo idioma:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ... 

Il modulo @staticmethod è un decorator di funzioni: per i dettagli vedere la descrizione delle definizioni di funzione nelle definizioni di funzione .

Può essere chiamato sulla classe (come Cf() ) o su un'istanza (come C().f() ). L'istanza viene ignorata tranne che per la sua classe.

I metodi statici in Python sono simili a quelli trovati in Java o C ++. Per un concetto più avanzato, vedi classmethod() in questa sezione.


Un metodo statico è un metodo che non conosce la classe o l'istanza su cui è stato chiamato. Ottiene solo gli argomenti che sono stati passati, nessun primo argomento implicito. Fondamentalmente è inutile in Python: puoi semplicemente usare una funzione modulo invece di un metodo statico.

Un metodo di classe , d'altra parte, è un metodo che riceve la classe su cui è stato chiamato, o la classe dell'istanza su cui è stato chiamato, come primo argomento. Ciò è utile quando si desidera che il metodo sia una factory per la classe: poiché ottiene la classe effettiva su cui è stato chiamato come primo argomento, è sempre possibile creare un'istanza della classe corretta, anche quando sono coinvolte sottoclassi. Osserva per esempio come dict.fromkeys() , un classmethod, restituisce un'istanza della sottoclasse quando viene chiamata su una sottoclasse:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

#!/usr/bin/python
#coding:utf-8

class Demo(object):
    def __init__(self,x):
        self.x = x

    @classmethod
    def addone(self, x):
        return x+1

    @staticmethod
    def addtwo(x):
        return x+2

    def addthree(self, x):
        return x+3

def main():
    print Demo.addone(2)
    print Demo.addtwo(2)

    #print Demo.addthree(2) #Error
    demo = Demo(2)
    print demo.addthree(2)


if __name__ == '__main__':
    main()

metodo di classe rispetto al metodo statico in Python

Metodo di classe

Il decoratore @classmethod è un decoratore di funzioni incorporato che è un'espressione che viene valutata dopo la definizione della funzione. Il risultato di tale valutazione ombreggia la definizione della tua funzione.

Un metodo di classe riceve la classe come primo argomento implicito, proprio come un metodo di istanza riceve l'istanza

Sintassi:

class C(object):
    @classmethod
    def fun(cls, arg1, arg2, ...):
       ....

fun: function that needs to be converted into a class method
returns: a class method for function.
  • Un metodo di classe è un metodo che è legato alla classe e non all'oggetto della classe.
  • Hanno accesso allo stato della classe poiché accetta un parametro di classe che punta alla classe e non all'istanza dell'oggetto.
  • Può modificare uno stato di classe applicabile a tutte le istanze della classe. Ad esempio può modificare una variabile di classe che sarà applicabile a tutte le istanze.

Metodo statico

Un metodo statico non riceve un primo argomento implicito.

Sintassi:

class C(object):
    @staticmethod
    def fun(arg1, arg2, ...):
        ...
returns: a static method for function fun.
  • Un metodo statico è anche un metodo che è legato alla classe e non all'oggetto della classe.
  • Un metodo statico non può accedere o modificare lo stato della classe.
  • È presente in una classe perché ha senso che il metodo sia presente in classe.

Metodo di classe rispetto al metodo statico

  • Un metodo di classe prende cls come primo parametro mentre un metodo statico non ha bisogno di parametri specifici.
  • Un metodo di classe può accedere o modificare lo stato della classe mentre un metodo statico non può accedervi o modificarlo.
  • Usiamo @classmethod decorator in python per creare un metodo di classe e usiamo @staticmethod decorator per creare un metodo statico in python.

Quando usare cosa?

  • Generalmente utilizziamo il metodo di classe per creare metodi di fabbrica. I metodi factory restituiscono oggetto di classe (simile a un costruttore) per diversi casi d'uso.
  • Generalmente utilizziamo metodi statici per creare funzioni di utilità.

Come definire un metodo di classe e un metodo statico?

Per definire un metodo di classe in python, usiamo @classmethod decorator e per definire un metodo statico usiamo @staticmethod decorator.

Vediamo un esempio per capire la differenza tra entrambi. Diciamo che vogliamo creare una classe Persona. Ora, python non supporta l'overloading dei metodi come C ++ o Java, quindi usiamo metodi di classe per creare metodi di fabbrica. Nell'esempio seguente utilizziamo un metodo di classe per creare un oggetto persona dall'anno di nascita.

Come spiegato sopra, utilizziamo metodi statici per creare funzioni di utilità. Nell'esempio seguente utilizziamo un metodo statico per verificare se una persona è adulta o no.

Implementazione

# Python program to demonstrate 
# use of class method and static method.
from datetime import date

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # a class method to create a Person object by birth year.
    @classmethod
    def fromBirthYear(cls, name, year):
        return cls(name, date.today().year - year)

    # a static method to check if a Person is adult or not.
    @staticmethod
    def isAdult(age):
        return age > 18

person1 = Person('mayank', 21)
person2 = Person.fromBirthYear('mayank', 1996)

print person1.age
print person2.age

# print the result
print Person.isAdult(22)

Produzione

21
21
True

Reference


@classmethod: può essere usato per creare un accesso globale condiviso a tutte le istanze create da quella classe ..... come aggiornare un record da più utenti .... Ho trovato particolarmente utile quando si creano anche singleton .. )

Metodo @static: non ha nulla a che fare con la classe o l'istanza associata a ... ma per la leggibilità è possibile utilizzare il metodo statico


@staticmethod disabilita semplicemente la funzione predefinita come descrittore del metodo. classmethod avvolge la tua funzione in un contenitore callable che passa un riferimento alla classe proprietaria come primo argomento:

>>> class C(object):
...  pass
... 
>>> def f():
...  pass
... 
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>

In effetti, classmethod ha un sovraccarico di runtime ma consente di accedere alla classe proprietaria. In alternativa, consiglio di utilizzare una metaclasse e di mettere i metodi di classe su quel metaclasse:

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()
<class '__main__.C'>

extend (L) estende l'elenco aggiungendo tutti gli elementi nell'elenco L specificato.

>>> a
[1, 2, 3]
a.extend([4)  #is eqivalent of a[len(a):] = [4]
>>>a
[1, 2, 3, 4]
a =[1,2,3]
>>> a
[1, 2, 3]
>>> a[len(a):] = [4]
>>> a
[1, 2, 3, 4]




python oop methods python-decorators