Introduction
Cette section traite de quelques décorateurs intégrés utilisés en combinaison avec les définitions de méthodes.
This tutorial is from open-source community. Access the source code
💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici
Cette section traite de quelques décorateurs intégrés utilisés en combinaison avec les définitions de méthodes.
Il existe des décorateurs prédéfinis utilisés pour spécifier des types spéciaux de méthodes dans les définitions de classes.
class Foo:
def bar(self,a):
...
@staticmethod
def spam(a):
...
@classmethod
def grok(cls,a):
...
@property
def name(self):
...
Allons-y un par un.
@staticmethod
est utilisé pour définir une soi-disant méthode de classe statique (du C++/Java). Une méthode statique est une fonction qui fait partie de la classe, mais qui ne fonctionne pas sur les instances.
class Foo(object):
@staticmethod
def bar(x):
print('x =', x)
>>> Foo.bar(2) ## x=2
>>>
Les méthodes statiques sont parfois utilisées pour implémenter le code d'assistance interne pour une classe. Par exemple, le code pour aider à gérer les instances créées (gestion de la mémoire, ressources système, persistance, verrouillage, etc.). Elles sont également utilisées par certains patrons de conception (non discutés ici).
@classmethod
est utilisé pour définir des méthodes de classe. Une méthode de classe est une méthode qui reçoit l'objet classe en tant que premier paramètre au lieu de l'instance.
class Foo:
def bar(self):
print(self)
@classmethod
def spam(cls):
print(cls)
>>> f = Foo()
>>> f.bar()
<__main__.Foo object at 0x971690> ## L'instance `f`
>>> Foo.spam()
<class '__main__.Foo'> ## La classe `Foo`
>>>
Les méthodes de classe sont le plus souvent utilisées comme outil pour définir des constructeurs alternatifs.
class Date:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
@classmethod
def today(cls):
## Remarquez comment la classe est passée en tant qu'argument
tm = time.localtime()
## Et utilisée pour créer une nouvelle instance
return cls(tm.tm_year, tm.tm_mon, tm.tm_mday)
d = Date.today()
Les méthodes de classe résolvent certains problèmes complexes liés aux fonctionnalités telles que l'héritage.
class Date:
...
@classmethod
def today(cls):
## Obtient la bonne classe (par exemple `NewDate`)
tm = time.localtime()
return cls(tm.tm_year, tm.tm_mon, tm.tm_mday)
class NewDate(Date):
...
d = NewDate.today()
Dans vos fichiers report.py
et portfolio.py
, la création d'un objet Portfolio
est un peu embrouillée. Par exemple, le programme report.py
a du code comme ceci :
def read_portfolio(filename, **opts):
'''
Lit un fichier de portefeuille d'actions dans une liste de dictionnaires avec les clés
name, shares et price.
'''
with open(filename) as lines:
portdicts = fileparse.parse_csv(lines,
select=['name','shares','price'],
types=[str,int,float],
**opts)
portfolio = [ Stock(**d) for d in portdicts ]
return Portfolio(portfolio)
et le fichier portfolio.py
définit Portfolio()
avec un initialisateur étrange comme ceci :
class Portfolio:
def __init__(self, holdings):
self._holdings = holdings
...
Franchement, la chaîne de responsabilité est un peu confuse car le code est dispersé. Si une classe Portfolio
est supposée contenir une liste d'instances Stock
, peut-être devriez-vous modifier la classe pour qu'elle soit un peu plus claire. Comme ceci :
## portfolio.py
import stock
class Portfolio:
def __init__(self):
self._holdings = []
def append(self, holding):
if not isinstance(holding, stock.Stock):
raise TypeError('Expected a Stock instance')
self._holdings.append(holding)
...
Si vous voulez lire un portefeuille à partir d'un fichier CSV, peut-être devriez-vous en faire une méthode de classe :
## portfolio.py
import fileparse
import stock
class Portfolio:
def __init__(self):
self._holdings = []
def append(self, holding):
if not isinstance(holding, stock.Stock):
raise TypeError('Expected a Stock instance')
self._holdings.append(holding)
@classmethod
def from_csv(cls, lines, **opts):
self = cls()
portdicts = fileparse.parse_csv(lines,
select=['name','shares','price'],
types=[str,int,float],
**opts)
for d in portdicts:
self.append(stock.Stock(**d))
return self
Pour utiliser cette nouvelle classe Portfolio
, vous pouvez maintenant écrire du code comme ceci :
>>> from portfolio import Portfolio
>>> with open('portfolio.csv') as lines:
... port = Portfolio.from_csv(lines)
...
>>>
Apportez ces modifications à la classe Portfolio
et modifiez le code de report.py
pour utiliser la méthode de classe.
Félicitations ! Vous avez terminé le laboratoire sur les méthodes décorées. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.