目录 | 上一节 (3.6 设计讨论) | 下一节 (4.2 继承)html
本节介绍 class 语句以及建立新对象的方式。python
面向对象编程是一种将代码组织成对象集合的编程技术。git
一个对象包括:github
在本课程中,你已经使用了面向对象编程技术。编程
例如,操做列表。数据结构
>>> nums = [1, 2, 3] >>> nums.append(4) # Method >>> nums.insert(1,10) # Method >>> nums [1, 10, 2, 3, 4] # Data >>>
nums
是列表的实例(instance)。app
方法(append()
和 insert()
)被绑定到实例(nums
)上。函数
class
语句使用 class
语句定义一个新的对象。oop
class Player: def __init__(self, x, y): self.x = x self.y = y self.health = 100 def move(self, dx, dy): self.x += dx self.y += dy def damage(self, pts): self.health -= pts
简而言之,类是一组函数,对所谓的 实例(instance) 执行各类操做。post
实例是你在程序中操做的实际对象。
经过像调用函数同样调用类来建立实例。
>>> a = Player(2, 3) >>> b = Player(10, 20) >>>
a
和 b
都是 Player
类的实例。
强调:class 语句仅仅是一个定义(它自己不执行任何操做)。相似于函数定义。
每一个实例都拥有本身的局部数据。
>>> a.x 2 >>> b.x 10
数据经过 _init__()
方法进行初始化。
class Player: def __init__(self, x, y): # Any value stored on `self` is instance data self.x = x self.y = y self.health = 100
对属性的总数或者类型没有限制。
应用于对象实例的函数称为实例方法。
class Player: ... # `move` is a method def move(self, dx, dy): self.x += dx self.y += dy
对象自己始终做为第一个参数传递。
>>> a.move(1, 2) # matches `a` to `self` # matches `1` to `dx` # matches `2` to `dy` def move(self, dx, dy):
按照惯例,实例称为 self
。可是,使用的实际名字不重要。对象始终做为第一个参数传递。将这个参数称为 self
只是 Python 的编程风格。
类未定义名称的做用域。
class Player: ... def move(self, dx, dy): self.x += dx self.y += dy def left(self, amt): move(-amt, 0) # NO. Calls a global `move` function self.move(-amt, 0) # YES. Calls method `move` from above.
若是想要对实例进行操做,那么你始终须要显式地引用它(如: self
)。
从本组练习开始,咱们将对前面章节的现有代码进行一系列更改。从练习 3.18 版本的代码开始很是重要。若是你尚未这些代码,请到 Solutions/3_18
目录下查看,而后复制它。
在第 2 和第 3 节中,咱们使用了了以元组和字典表示的数据。例如,持有的股票能够用像下面这样的元组表示:
s = ('GOOG',100,490.10)
或者使用像下面这样的字典表示:
s = { 'name' : 'GOOG', 'shares' : 100, 'price' : 490.10 }
你甚至能够编写用于操做此类数据的函数。例如:
def cost(s): return s['shares'] * s['price']
可是,随着程序规模的不断扩大,你可能但愿建立更好的代码组织意识(sense)。所以,能够定义一个类表示数据。请建立一个名为 stock.py
的文件,并定义一个名为 Stock
的类,用以表示持有的单支股票。Stock
类具备 name
, shares
,和 price
属性。示例:
>>> import stock >>> a = stock.Stock('GOOG',100,490.10) >>> a.name 'GOOG' >>> a.shares 100 >>> a.price 490.1 >>>
建立更多的 Stock
对象并对其进行操做。示例:
>>> b = stock.Stock('AAPL', 50, 122.34) >>> c = stock.Stock('IBM', 75, 91.75) >>> b.shares * b.price 6117.0 >>> c.shares * c.price 6881.25 >>> stocks = [a, b, c] >>> stocks [<stock.Stock object at 0x37d0b0>, <stock.Stock object at 0x37d110>, <stock.Stock object at 0x37d050>] >>> for s in stocks: print(f'{s.name:>10s} {s.shares:>10d} {s.price:>10.2f}') ... look at the output ... >>>
须要强调的一点是,在这里, Stock
类充当建立实例对象的工厂。基本上,你能够像调用函数同样调用类为你建立新对象。另外,必须强调的是,每个对象都是不一样的——它们拥有各自的数据,这些数据与以建立的其它对象是分开的。
某种程度上,经过类定义的对象与字典相似——只是使用颇为不一样的语法。例如,使用的是 s.name
和 s.price
,而不是 s['name']
和 s['price']
。
拥有对象后,你能够添加方法到对象上。众所皆知,方法就是对存储在对象内部的数据进行操做的函数。请给 Stock
对象添加 cost()
和 sell()
方法。它们应该像下面这样工做:
>>> import stock >>> s = stock.Stock('GOOG', 100, 490.10) >>> s.cost() 49010.0 >>> s.shares 100 >>> s.sell(25) >>> s.shares 75 >>> s.cost() 36757.5 >>>
尝试执行如下步骤,从列表字典中建立 Stock 的实例列表。而后计算总费用:
>>> import fileparse >>> with open('Data/portfolio.csv') as lines: ... portdicts = fileparse.parse_csv(lines, select=['name','shares','price'], types=[str,int,float]) ... >>> portfolio = [ stock.Stock(d['name'], d['shares'], d['price']) for d in portdicts] >>> portfolio [<stock.Stock object at 0x10c9e2128>, <stock.Stock object at 0x10c9e2048>, <stock.Stock object at 0x10c9e2080>, <stock.Stock object at 0x10c9e25f8>, <stock.Stock object at 0x10c9e2630>, <stock.Stock object at 0x10ca6f748>, <stock.Stock object at 0x10ca6f7b8>] >>> sum([s.cost() for s in portfolio]) 44671.15 >>>
请修改 report.py
程序里面的 read_portfolio()
函数,以便如练习 4.3 所示那样,读取股票投资组合到 Stock
的实例列表里面。修改完后,修复(fix)report.py
和 pcost.py
里面全部的代码,以便使用 Stock
的实例进行工做,而不是使用字典。
提示:你没必要对代码进行大量更改,主要是将字典访问,如 s['shares']
更改成 s.shares
。
修改完后应该可以像以前同样运行函数:
>>> import pcost >>> pcost.portfolio_cost('Data/portfolio.csv') 44671.15 >>> import report >>> report.portfolio_report('Data/portfolio.csv', 'Data/prices.csv') Name Shares Price Change ---------- ---------- ---------- ---------- AA 100 9.22 -22.98 IBM 50 106.28 15.18 CAT 150 35.46 -47.98 MSFT 200 20.89 -30.34 GE 95 13.48 -26.89 MSFT 50 20.89 -44.21 IBM 100 106.28 35.84 >>>