Introducción
Esta sección discute algunos decoradores integrados que se utilizan en combinación con las definiciones de métodos.
This tutorial is from open-source community. Access the source code
💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí
Esta sección discute algunos decoradores integrados que se utilizan en combinación con las definiciones de métodos.
Hay decoradores predefinidos que se utilizan para especificar tipos especiales de métodos en las definiciones de clases.
class Foo:
def bar(self,a):
...
@staticmethod
def spam(a):
...
@classmethod
def grok(cls,a):
...
@property
def name(self):
...
Vamos a ver uno por uno.
@staticmethod
se utiliza para definir los llamados métodos estáticos de una clase (del C++/Java). Un método estático es una función que es parte de la clase, pero que no opera sobre instancias.
class Foo(object):
@staticmethod
def bar(x):
print('x =', x)
>>> Foo.bar(2) ## x=2
>>>
Los métodos estáticos a veces se utilizan para implementar el código de soporte interno para una clase. Por ejemplo, código para ayudar a administrar las instancias creadas (gestión de memoria, recursos del sistema, persistencia, bloqueo, etc.). También se utilizan en ciertos patrones de diseño (no se discuten aquí).
@classmethod
se utiliza para definir métodos de clase. Un método de clase es un método que recibe el objeto de la clase como primer parámetro en lugar de la instancia.
class Foo:
def bar(self):
print(self)
@classmethod
def spam(cls):
print(cls)
>>> f = Foo()
>>> f.bar()
<__main__.Foo object at 0x971690> ## La instancia `f`
>>> Foo.spam()
<class '__main__.Foo'> ## La clase `Foo`
>>>
Los métodos de clase se utilizan con más frecuencia como una herramienta para definir constructores alternativos.
class Date:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
@classmethod
def today(cls):
## Observe cómo la clase se pasa como argumento
tm = time.localtime()
## Y se utiliza para crear una nueva instancia
return cls(tm.tm_year, tm.tm_mon, tm.tm_mday)
d = Date.today()
Los métodos de clase resuelven algunos problemas complicados con características como la herencia.
class Date:
...
@classmethod
def today(cls):
## Obtiene la clase correcta (por ejemplo, `NewDate`)
tm = time.localtime()
return cls(tm.tm_year, tm.tm_mon, tm.tm_mday)
class NewDate(Date):
...
d = NewDate.today()
En sus archivos report.py
y portfolio.py
, la creación de un objeto Portfolio
está un poco confusa. Por ejemplo, el programa report.py
tiene código como este:
def read_portfolio(filename, **opts):
'''
Lee un archivo de cartera de acciones en una lista de diccionarios con claves
name, shares y 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)
y el archivo portfolio.py
define Portfolio()
con un inicializador extraño como este:
class Portfolio:
def __init__(self, holdings):
self._holdings = holdings
...
Frankmente, la cadena de responsabilidad es un poco confusa porque el código está disperso. Si una clase Portfolio
está supuesta a contener una lista de instancias de Stock
, quizás debería cambiar la clase para que sea un poco más clara. Así:
## 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 desea leer una cartera desde un archivo CSV, quizás debería crear un método de clase para ello:
## 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
Para usar esta nueva clase Portfolio
, ahora puede escribir código como este:
>>> from portfolio import Portfolio
>>> with open('portfolio.csv') as lines:
... port = Portfolio.from_csv(lines)
...
>>>
Haga estos cambios a la clase Portfolio
y modifique el código de report.py
para usar el método de clase.
¡Felicitaciones! Has completado el laboratorio de Métodos Decorados. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.