作者:麦叔 来源:麦叔编程回顾和问题 上一篇文章,我们讲解了NamedTuple。它可以让我们像使用对象一样使用元组,避免魔术数字,让代码更安全,更易于理解,也比普通对象更快。 下面是其中的例子。有兴趣的麦友可以在合集中往前翻,找到上一篇文章。fromtypingimportNamedTupleclassStock(NamedTuple):name:strhigh:floatlow:floatend:floatstock1Stock(苹果,100,80,88)stock2Stock(name百度,high80,low63,end65)print(stock2。high)print(stock2。low)print(stock2。end) 但命名元组有个问题。它的数据是不能修改的,这是元组的重要特点。 那如果我的对象需要修改,怎么办呢?这就是本文的重点!使用dataclass 从Python3。7开始,我们可以用很简洁的语法定义只有属性的类,也就是dataclass。从表面上看,它们非常像命名元组。 下面是dataclass版本的Stock:fromdataclassesimportdataclassdataclassclassStock:symbol:strcurrent:floathigh:floatlow:float 这个例子中,它的定义几乎和NamedTuple定义完全相同。 dataclass函数是一个类装饰器,使用符号。dataclass包含状态且可以被修改,重要的是它的功能很强大。 下面是创建Stock实例的例子:sStock(AAPL,123。52,137。98,53。15) 一旦实例化,Stock对象可以像普通类一样使用。你可以访问和更新它的属性:sStock(symbolAAPL,current123。52,high137。98,low53。15)s。current123。52s。current122。25sStock(symbolAAPL,current122。25,high137。98,low53。15)优点多多 我们来看看,dataclass相比普通的类有什么优点。 下面是一个功能类似的普通类:classStockOrdinary:definit(self,name:str,current:float,high:float,low:float)None:self。namenameself。currentcurrentself。highhighself。lowlowsordStockOrdinary(AAPL,123。52,137。98,53。15) 好处1:dataclass只需要写一次属性名,不需要在init()方法的参数和方法体中重复。 好处2:dataclass也提供了一个比object类更加友好的字符串表达。 好处3:dataclass也包含相等比较运算。 下面的例子可以比较普通类和dataclass的区别:sordmain。StockOrdinaryobjectat0x7fb833c63f10sord2StockOrdinary(AAPL,123。52,137。98,53。15)sordsord2False 普通类的默认字符串表达看起来很糟糕,而且它没有相等运算。dataclass的情况就要好多了:stock2Stock(symbolAAPL,current122。25,high137。98,low53。15)sstock2True 好处4:你可以为属性指定默认值。 也许股票市场闭市了,你不知道今天股票的价格是什么:dataclassclassStockDefaults:name:strcurrent:float0。0high:float0。0low:float0。0 你可以只用股票名称来创建对象。其他的值会使用默认值:StockDefaults(GOOG)StockDefaults(nameGOOG,current0。0,high0。0,low0。0) 好处5:你可以轻松的添加比较运算,如下所示:dataclass(orderTrue)classStockOrdered:name:strcurrent:float0。0high:float0。0low:float0。0 你也许会问:就这么简单? 是的!给装饰器添加orderTrue参数,就会创建所有的比较运算方法。这使得我们可以比较对象实例,也可以排序。就像下面这样:stockordered1StockOrdered(GOOG,1826。77,1847。20,1013。54)stockordered2StockOrdered(GOOG)stockordered3StockOrdered(GOOG,1728。28,high1733。18,low1666。33)stockordered1stockordered2Falsestockordered1stockordered2Truefrompprintimportpprintpprint(sorted(〔stockordered1,stockordered2,stockordered3〕))〔StockOrdered(nameGOOG,current0。0,high0。0,low0。0),StockOrdered(nameGOOG,current1728。28,high1733。18,low1666。33),StockOrdered(nameGOOG,current1826。77,high1847。2,low1013。54)〕麦叔寄语 下次创建类的时候,试试看dataclass,写很少的代码就有很强大的功能。 dataclass也可以像普通类一样,添加所需要的实例方法或类方法。