上一节(7.4装饰器)|下一节(8测试和调试)7.5装饰方法本节讨论一些与方法定义结合使用的内置装饰器。预定义装饰器在类定义中,有许多预定义装饰器用于指定特定类型的方法。classFoo:defbar(self,a):...@staticmethoddefspam(a):...@classmethoddefgrok(cls,a):...@propertydefname(self):...let让我们一一过一遍。静态方法@staticmethod用于定义所谓的静态类方法(staticclassmethod,来自C++/Java)。静态方法是属于类的一部分但不对实例进行操作的函数。classFoo(object):@staticmethoddefbar(x):print('x=',x)>>>Foo.bar(2)x=2>>>静态方法有时用于实现内部支持代码一个类,例如帮助管理创建的实例(内存管理、系统资源、持久化、锁等)。它有时也用于某些设计模式(这里不讨论)。类方法@classmethod用于定义类方法(classmethods)。类方法是一种将类对象而不是实例作为其第一个参数的方法。classFoo:defbar(self):print(self)@classmethoddefspam(cls):print(cls)>>>f=Foo()>>>f.bar()<__main__.Fooobjectat0x971690>#Theinstance`f`>>>Foo.spam()#Theclass`Foo`>>>类方法通常用作定义替代构造函数的工具。importtimeclassDate:def__init__(self,year,month,day):self.year=yearself.month=monthself.day=day@classmethoddeftoday(cls):#注意类是如何作为参数传递的tm=time.localtime()#并用于创建一个新实例returncls(tm.tm_year,tm.tm_mon,tm.tm_mday)d=Date.today()类方法可以与继承等特性一起使用来解决棘手的问题。classDate:...@classmethoddeftoday(cls):#获取正确的类(例如`NewDate`)tm=time.localtime()returncls(tm.tm_year,tm.tm_mon,tm.tm_mday)classNewDate(Date):...d=NewDate.today()Exercise练习7.11:类方法实战在report.py和portfolio.py文件中,Portfolio类的创建有点混乱。例如,report.py程序具有以下代码:defread_portfolio(filename,**opts):'''将股票投资组合文件读入包含名称、股票和价格键的字典列表中。'''withopen(filename)aslines:portdicts=fileparse.parse_csv(lines,select=['name','shares','price'],types=[str,int,float],**opts)投资组合=[Stock(**d)fordinportdicts]returnPortfolio(portfolio)并且portfolio.py文件中定义的投资组合有一个奇怪的初始化:classPortfolio:def__init__(self,holdings):self.holdings=holdings。..坦白说,因为代码分散在各个文件中,所以责任链有点混乱。如果Portfolio类应包含Stock类的实例列表,那么您应该修改该类以使其更清晰。示例:#portfolio.pyimportstockclassPortfolio:def__init__(self):self.holdings=[]defappend(self,holding):ifnotisinstance(holding,stock.Stock):raiseTypeError('ExpectedaStockinstance')self.holdings.append(holding)...如果您想从CSV文件中读取投资组合数据,那么您应该为此创建一个类方法:#portfolio.pyimportfileparseimportstockclassPortfolio:def__init__(self):self。holdings=[]defappend(self,holding):如果不是isinstance(holding,stock.Stock):raiseTypeError('ExpectedaStockinstance')self.holdings.append(holding)@classmethoddeffrom_csv(cls,lines,**opts):self=cls()portdicts=fileparse.parse_csv(lines,select=['name','shares','price'],types=[str,int,float],**opts)ford在portdicts中:self.append(stock.Stock(**d))returnself要使用新的Portfolio类,您可以编写如下代码:>>>fromportfolioimportPortfolio>>>withopen('Data/portfolio.csv')aslines:...port=Portfolio.from_csv(lines)...>>>请修改Portfolio类,然后修改report.py的代码使用类方法目录|上一节(7.4装饰器)|下一节(8测试和调试)注意:完整翻译见https://github.com/codists/practical-python-zh