Introduction
This section discusses a few built-in decorators that are used in combination with method definitions.
This tutorial is from open-source community. Access the source code
This section discusses a few built-in decorators that are used in combination with method definitions.
There are predefined decorators used to specify special kinds of methods in class definitions.
class Foo:
def bar(self,a):
...
@staticmethod
def spam(a):
...
@classmethod
def grok(cls,a):
...
@property
def name(self):
...
Let's go one by one.
@staticmethod
is used to define a so-called static class methods (from C++/Java). A static method is a function that is part of the class, but which does not operate on instances.
class Foo(object):
@staticmethod
def bar(x):
print('x =', x)
>>> Foo.bar(2) ## x=2
>>>
Static methods are sometimes used to implement internal supporting code for a class. For example, code to help manage created instances (memory management, system resources, persistence, locking, etc). They're also used by certain design patterns (not discussed here).
@classmethod
is used to define class methods. A class method is a method that receives the class object as the first parameter instead of the instance.
class Foo:
def bar(self):
print(self)
@classmethod
def spam(cls):
print(cls)
>>> f = Foo()
>>> f.bar()
<__main__.Foo object at 0x971690> ## The instance `f`
>>> Foo.spam()
<class '__main__.Foo'> ## The class `Foo`
>>>
Class methods are most often used as a tool for defining alternate constructors.
class Date:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
@classmethod
def today(cls):
## Notice how the class is passed as an argument
tm = time.localtime()
## And used to create a new instance
return cls(tm.tm_year, tm.tm_mon, tm.tm_mday)
d = Date.today()
Class methods solve some tricky problems with features like inheritance.
class Date:
...
@classmethod
def today(cls):
## Gets the correct class (e.g. `NewDate`)
tm = time.localtime()
return cls(tm.tm_year, tm.tm_mon, tm.tm_mday)
class NewDate(Date):
...
d = NewDate.today()
In your report.py
and portfolio.py
files, the creation of a Portfolio
object is a bit muddled. For example, the report.py
program has code like this:
def read_portfolio(filename, **opts):
'''
Read a stock portfolio file into a list of dictionaries with keys
name, shares, and 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)
and the portfolio.py
file defines Portfolio()
with an odd initializer like this:
class Portfolio:
def __init__(self, holdings):
self._holdings = holdings
...
Frankly, the chain of responsibility is all a bit confusing because the code is scattered. If a Portfolio
class is supposed to contain a list of Stock
instances, maybe you should change the class to be a bit more clear. Like this:
## 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)
...
If you want to read a portfolio from a CSV file, maybe you should make a class method for it:
## 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
To use this new Portfolio class, you can now write code like this:
>>> from portfolio import Portfolio
>>> with open('portfolio.csv') as lines:
... port = Portfolio.from_csv(lines)
...
>>>
Make these changes to the Portfolio
class and modify the report.py
code to use the class method.
Congratulations! You have completed the Decorated Methods lab. You can practice more labs in LabEx to improve your skills.